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

/*
 * Copyright (C) 2011-2012 Daiki Ueno <ueno@unixuser.org>
 * Copyright (C) 2011-2012 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;
#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;

#define SKK_TYPE_ROM_KANA_ENTRY (skk_rom_kana_entry_get_type ())
typedef struct _SkkRomKanaEntry SkkRomKanaEntry;
#define __vala_JsonArray_free0(var) ((var == NULL) ? NULL : (var = (_vala_JsonArray_free (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;

#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 __vala_JsonObject_free0(var) ((var == NULL) ? NULL : (var = (_vala_JsonObject_free (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;
enum  {
	SKK_KEYMAP_MAP_FILE_DUMMY_PROPERTY
};
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;
enum  {
	SKK_ROM_KANA_MAP_FILE_DUMMY_PROPERTY
};
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);
static JsonArray* _vala_JsonArray_copy (JsonArray* self);
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);
static void _vala_JsonArray_free (JsonArray* self);
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))
enum  {
	SKK_RULE_DUMMY_PROPERTY,
	SKK_RULE_METADATA
};
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);
static JsonObject* _vala_JsonObject_copy (JsonObject* self);
static void _vala_JsonObject_free (JsonObject* 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);
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_;
	const gchar* _tmp1_;
	gboolean _tmp2_ = FALSE;
	GError * _inner_error_ = NULL;
	g_return_val_if_fail (metadata != NULL, NULL);
	g_return_val_if_fail (mode != NULL, NULL);
	_tmp0_ = *metadata;
	_tmp1_ = mode;
	self = (SkkKeymapMapFile*) skk_map_file_construct (object_type, &_tmp0_, "keymap", _tmp1_, &_inner_error_);
	if (_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;
		}
	}
	_tmp2_ = skk_map_file_has_map ((SkkMapFile*) self, "keymap");
	if (_tmp2_) {
		GeeMap* _tmp3_ = NULL;
		GeeMap* map;
		SkkKeymap* _tmp4_;
		_tmp3_ = skk_map_file_get ((SkkMapFile*) self, "keymap");
		map = _tmp3_;
		_tmp4_ = skk_keymap_new ();
		_g_object_unref0 (self->keymap);
		self->keymap = _tmp4_;
		{
			GeeMap* _tmp5_;
			GeeSet* _tmp6_;
			GeeSet* _tmp7_;
			GeeSet* _tmp8_;
			GeeIterator* _tmp9_ = NULL;
			GeeIterator* _tmp10_;
			GeeIterator* _key_it;
			_tmp5_ = map;
			_tmp6_ = gee_map_get_keys (_tmp5_);
			_tmp7_ = _tmp6_;
			_tmp8_ = _tmp7_;
			_tmp9_ = gee_iterable_iterator ((GeeIterable*) _tmp8_);
			_tmp10_ = _tmp9_;
			_g_object_unref0 (_tmp8_);
			_key_it = _tmp10_;
			while (TRUE) {
				GeeIterator* _tmp11_;
				gboolean _tmp12_ = FALSE;
				GeeIterator* _tmp13_;
				gpointer _tmp14_ = NULL;
				gchar* key;
				GeeMap* _tmp15_;
				const gchar* _tmp16_;
				gpointer _tmp17_ = NULL;
				JsonNode* value;
				SkkKeymap* _tmp18_;
				const gchar* _tmp19_;
				JsonNode* _tmp20_;
				const gchar* _tmp21_ = NULL;
				_tmp11_ = _key_it;
				_tmp12_ = gee_iterator_next (_tmp11_);
				if (!_tmp12_) {
					break;
				}
				_tmp13_ = _key_it;
				_tmp14_ = gee_iterator_get (_tmp13_);
				key = (gchar*) _tmp14_;
				_tmp15_ = map;
				_tmp16_ = key;
				_tmp17_ = gee_map_get (_tmp15_, _tmp16_);
				value = (JsonNode*) _tmp17_;
				_tmp18_ = self->keymap;
				_tmp19_ = key;
				_tmp20_ = value;
				_tmp21_ = json_node_get_string (_tmp20_);
				skk_keymap_set (_tmp18_, _tmp19_, _tmp21_);
				__vala_JsonNode_free0 (value);
				_g_free0 (key);
			}
			_g_object_unref0 (_key_it);
		}
		_g_object_unref0 (map);
	} else {
		GError* _tmp22_;
		_tmp22_ = g_error_new_literal (SKK_RULE_PARSE_ERROR, SKK_RULE_PARSE_ERROR_FAILED, "no keymap entry");
		_inner_error_ = _tmp22_;
		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 JsonArray* _vala_JsonArray_copy (JsonArray* self) {
	return g_boxed_copy (json_array_get_type (), self);
}


static gpointer __vala_JsonArray_copy0 (gpointer self) {
	return self ? _vala_JsonArray_copy (self) : NULL;
}


static void _vala_JsonArray_free (JsonArray* self) {
	g_boxed_free (json_array_get_type (), self);
}


static SkkRomKanaNode* skk_rom_kana_map_file_parse_rule (SkkRomKanaMapFile* self, GeeMap* map, GError** error) {
	SkkRomKanaNode* result = NULL;
	SkkRomKanaNode* _tmp0_;
	SkkRomKanaNode* node;
	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_;
	{
		GeeMap* _tmp1_;
		GeeSet* _tmp2_;
		GeeSet* _tmp3_;
		GeeSet* _tmp4_;
		GeeIterator* _tmp5_ = NULL;
		GeeIterator* _tmp6_;
		GeeIterator* _key_it;
		_tmp1_ = map;
		_tmp2_ = gee_map_get_keys (_tmp1_);
		_tmp3_ = _tmp2_;
		_tmp4_ = _tmp3_;
		_tmp5_ = gee_iterable_iterator ((GeeIterable*) _tmp4_);
		_tmp6_ = _tmp5_;
		_g_object_unref0 (_tmp4_);
		_key_it = _tmp6_;
		while (TRUE) {
			GeeIterator* _tmp7_;
			gboolean _tmp8_ = FALSE;
			GeeIterator* _tmp9_;
			gpointer _tmp10_ = NULL;
			gchar* key;
			GeeMap* _tmp11_;
			const gchar* _tmp12_;
			gpointer _tmp13_ = NULL;
			JsonNode* value;
			JsonNode* _tmp14_;
			JsonNodeType _tmp15_ = 0;
			_tmp7_ = _key_it;
			_tmp8_ = gee_iterator_next (_tmp7_);
			if (!_tmp8_) {
				break;
			}
			_tmp9_ = _key_it;
			_tmp10_ = gee_iterator_get (_tmp9_);
			key = (gchar*) _tmp10_;
			_tmp11_ = map;
			_tmp12_ = key;
			_tmp13_ = gee_map_get (_tmp11_, _tmp12_);
			value = (JsonNode*) _tmp13_;
			_tmp14_ = value;
			_tmp15_ = json_node_get_node_type (_tmp14_);
			if (_tmp15_ == JSON_NODE_ARRAY) {
				JsonNode* _tmp16_;
				JsonArray* _tmp17_ = NULL;
				JsonArray* _tmp18_;
				JsonArray* components;
				JsonArray* _tmp19_;
				guint _tmp20_ = 0U;
				guint length;
				gboolean _tmp21_ = FALSE;
				guint _tmp22_;
				gboolean _tmp24_;
				_tmp16_ = value;
				_tmp17_ = json_node_get_array (_tmp16_);
				_tmp18_ = __vala_JsonArray_copy0 (_tmp17_);
				components = _tmp18_;
				_tmp19_ = components;
				_tmp20_ = json_array_get_length (_tmp19_);
				length = _tmp20_;
				_tmp22_ = length;
				if (((guint) 2) <= _tmp22_) {
					guint _tmp23_;
					_tmp23_ = length;
					_tmp21_ = _tmp23_ <= ((guint) 4);
				} else {
					_tmp21_ = FALSE;
				}
				_tmp24_ = _tmp21_;
				if (_tmp24_) {
					JsonArray* _tmp25_;
					const gchar* _tmp26_ = NULL;
					gchar* _tmp27_;
					gchar* carryover;
					JsonArray* _tmp28_;
					const gchar* _tmp29_ = NULL;
					gchar* _tmp30_;
					gchar* hiragana;
					gchar* _tmp31_ = NULL;
					guint _tmp32_;
					const gchar* _tmp38_;
					gchar* _tmp39_;
					gchar* katakana;
					gchar* _tmp40_ = NULL;
					guint _tmp41_;
					const gchar* _tmp47_;
					gchar* _tmp48_;
					gchar* hankaku_katakana;
					const gchar* _tmp49_;
					gchar* _tmp50_;
					const gchar* _tmp51_;
					gchar* _tmp52_;
					const gchar* _tmp53_;
					gchar* _tmp54_;
					const gchar* _tmp55_;
					gchar* _tmp56_;
					const gchar* _tmp57_;
					gchar* _tmp58_;
					SkkRomKanaEntry _tmp59_ = {0};
					SkkRomKanaEntry entry;
					SkkRomKanaNode* _tmp60_;
					const gchar* _tmp61_;
					SkkRomKanaEntry _tmp62_;
					_tmp25_ = components;
					_tmp26_ = json_array_get_string_element (_tmp25_, (guint) 0);
					_tmp27_ = g_strdup (_tmp26_);
					carryover = _tmp27_;
					_tmp28_ = components;
					_tmp29_ = json_array_get_string_element (_tmp28_, (guint) 1);
					_tmp30_ = g_strdup (_tmp29_);
					hiragana = _tmp30_;
					_tmp32_ = length;
					if (_tmp32_ >= ((guint) 3)) {
						JsonArray* _tmp33_;
						const gchar* _tmp34_ = NULL;
						gchar* _tmp35_;
						_tmp33_ = components;
						_tmp34_ = json_array_get_string_element (_tmp33_, (guint) 2);
						_tmp35_ = g_strdup (_tmp34_);
						_g_free0 (_tmp31_);
						_tmp31_ = _tmp35_;
					} else {
						const gchar* _tmp36_;
						gchar* _tmp37_ = NULL;
						_tmp36_ = hiragana;
						_tmp37_ = skk_util_get_katakana (_tmp36_);
						_g_free0 (_tmp31_);
						_tmp31_ = _tmp37_;
					}
					_tmp38_ = _tmp31_;
					_tmp39_ = g_strdup (_tmp38_);
					katakana = _tmp39_;
					_tmp41_ = length;
					if (_tmp41_ == ((guint) 4)) {
						JsonArray* _tmp42_;
						const gchar* _tmp43_ = NULL;
						gchar* _tmp44_;
						_tmp42_ = components;
						_tmp43_ = json_array_get_string_element (_tmp42_, (guint) 3);
						_tmp44_ = g_strdup (_tmp43_);
						_g_free0 (_tmp40_);
						_tmp40_ = _tmp44_;
					} else {
						const gchar* _tmp45_;
						gchar* _tmp46_ = NULL;
						_tmp45_ = katakana;
						_tmp46_ = skk_util_get_hankaku_katakana (_tmp45_);
						_g_free0 (_tmp40_);
						_tmp40_ = _tmp46_;
					}
					_tmp47_ = _tmp40_;
					_tmp48_ = g_strdup (_tmp47_);
					hankaku_katakana = _tmp48_;
					_tmp49_ = key;
					_tmp50_ = g_strdup (_tmp49_);
					_tmp51_ = carryover;
					_tmp52_ = g_strdup (_tmp51_);
					_tmp53_ = hiragana;
					_tmp54_ = g_strdup (_tmp53_);
					_tmp55_ = katakana;
					_tmp56_ = g_strdup (_tmp55_);
					_tmp57_ = hankaku_katakana;
					_tmp58_ = g_strdup (_tmp57_);
					_g_free0 (_tmp59_.rom);
					_tmp59_.rom = _tmp50_;
					_g_free0 (_tmp59_.carryover);
					_tmp59_.carryover = _tmp52_;
					_g_free0 (_tmp59_.hiragana);
					_tmp59_.hiragana = _tmp54_;
					_g_free0 (_tmp59_.katakana);
					_tmp59_.katakana = _tmp56_;
					_g_free0 (_tmp59_.hankaku_katakana);
					_tmp59_.hankaku_katakana = _tmp58_;
					entry = _tmp59_;
					_tmp60_ = node;
					_tmp61_ = key;
					_tmp62_ = entry;
					skk_rom_kana_node_insert (_tmp60_, _tmp61_, &_tmp62_);
					skk_rom_kana_entry_destroy (&entry);
					_g_free0 (hankaku_katakana);
					_g_free0 (_tmp40_);
					_g_free0 (katakana);
					_g_free0 (_tmp31_);
					_g_free0 (hiragana);
					_g_free0 (carryover);
				} else {
					GError* _tmp63_;
					_tmp63_ = g_error_new_literal (SKK_RULE_PARSE_ERROR, SKK_RULE_PARSE_ERROR_FAILED, "\"rom-kana\" must have two to four elements");
					_inner_error_ = _tmp63_;
					if (_inner_error_->domain == SKK_RULE_PARSE_ERROR) {
						g_propagate_error (error, _inner_error_);
						__vala_JsonArray_free0 (components);
						__vala_JsonNode_free0 (value);
						_g_free0 (key);
						_g_object_unref0 (_key_it);
						_g_object_unref0 (node);
						return NULL;
					} else {
						__vala_JsonArray_free0 (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;
					}
				}
				__vala_JsonArray_free0 (components);
			} else {
				GError* _tmp64_;
				_tmp64_ = 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_ = _tmp64_;
				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_;
	gboolean _tmp1_ = FALSE;
	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 (_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;
		}
	}
	_tmp1_ = skk_map_file_has_map ((SkkMapFile*) self, "rom-kana");
	if (_tmp1_) {
		GeeMap* _tmp2_ = NULL;
		GeeMap* _tmp3_;
		SkkRomKanaNode* _tmp4_ = NULL;
		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_);
		_tmp6_ = _tmp5_;
		if (_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;
			}
		}
		_g_object_unref0 (self->root_node);
		self->root_node = _tmp6_;
	} 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;
	const gchar* _tmp0_;
	const gchar* _tmp1_;
	const gchar* _tmp2_;
	gchar* _tmp3_;
	gchar* _tmp4_;
	gchar* _tmp5_ = NULL;
	gchar* _tmp6_;
	gchar* filename;
	const gchar* _tmp7_;
	gboolean _tmp8_ = FALSE;
	g_return_val_if_fail (type != NULL, NULL);
	g_return_val_if_fail (name != NULL, NULL);
	_tmp0_ = (*self).base_dir;
	_tmp1_ = type;
	_tmp2_ = name;
	_tmp3_ = g_strconcat (_tmp2_, ".json", NULL);
	_tmp4_ = _tmp3_;
	_tmp5_ = g_build_filename (_tmp0_, _tmp1_, _tmp4_, NULL);
	_tmp6_ = _tmp5_;
	_g_free0 (_tmp4_);
	filename = _tmp6_;
	_tmp7_ = filename;
	_tmp8_ = g_file_test (_tmp7_, G_FILE_TEST_EXISTS);
	if (_tmp8_) {
		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 JsonObject* _vala_JsonObject_copy (JsonObject* self) {
	return g_boxed_copy (json_object_get_type (), self);
}


static gpointer __vala_JsonObject_copy0 (gpointer self) {
	return self ? _vala_JsonObject_copy (self) : NULL;
}


static void _vala_JsonObject_free (JsonObject* self) {
	g_boxed_free (json_object_get_type (), self);
}


static void skk_rule_load_metadata (const gchar* filename, SkkRuleMetadata* result, GError** error) {
	JsonParser* _tmp0_;
	JsonParser* parser;
	GError * _inner_error_ = NULL;
	g_return_if_fail (filename != NULL);
	_tmp0_ = json_parser_new ();
	parser = _tmp0_;
	{
		JsonParser* _tmp1_;
		const gchar* _tmp2_;
		gboolean _tmp3_ = FALSE;
		gboolean _tmp4_;
		JsonParser* _tmp7_;
		JsonNode* _tmp8_ = NULL;
		JsonNode* _tmp9_;
		JsonNode* root;
		JsonNode* _tmp10_;
		JsonNodeType _tmp11_ = 0;
		JsonNode* _tmp13_;
		JsonObject* _tmp14_ = NULL;
		JsonObject* _tmp15_;
		JsonObject* object;
		JsonNode* member = NULL;
		JsonObject* _tmp16_;
		gboolean _tmp17_ = FALSE;
		JsonObject* _tmp19_;
		JsonNode* _tmp20_ = NULL;
		JsonNode* _tmp21_;
		JsonNode* _tmp22_;
		const gchar* _tmp23_ = NULL;
		gchar* _tmp24_;
		gchar* name;
		JsonObject* _tmp25_;
		gboolean _tmp26_ = FALSE;
		JsonObject* _tmp28_;
		JsonNode* _tmp29_ = NULL;
		JsonNode* _tmp30_;
		JsonNode* _tmp31_;
		const gchar* _tmp32_ = NULL;
		gchar* _tmp33_;
		gchar* description;
		gchar* filter = NULL;
		JsonObject* _tmp34_;
		gboolean _tmp35_ = FALSE;
		const gchar* _tmp48_;
		gchar* _tmp49_;
		const gchar* _tmp50_;
		gchar* _tmp51_;
		const gchar* _tmp52_;
		gchar* _tmp53_;
		const gchar* _tmp54_;
		gchar* _tmp55_ = NULL;
		SkkRuleMetadata _tmp56_ = {0};
		_tmp1_ = parser;
		_tmp2_ = filename;
		_tmp3_ = json_parser_load_from_file (_tmp1_, _tmp2_, &_inner_error_);
		_tmp4_ = _tmp3_;
		if (_inner_error_ != NULL) {
			goto __catch24_g_error;
		}
		if (!_tmp4_) {
			const gchar* _tmp5_;
			GError* _tmp6_;
			_tmp5_ = filename;
			_tmp6_ = g_error_new (SKK_RULE_PARSE_ERROR, SKK_RULE_PARSE_ERROR_FAILED, "can't load %s", _tmp5_);
			_inner_error_ = _tmp6_;
			goto __catch24_g_error;
		}
		_tmp7_ = parser;
		_tmp8_ = json_parser_get_root (_tmp7_);
		_tmp9_ = __vala_JsonNode_copy0 (_tmp8_);
		root = _tmp9_;
		_tmp10_ = root;
		_tmp11_ = json_node_get_node_type (_tmp10_);
		if (_tmp11_ != JSON_NODE_OBJECT) {
			GError* _tmp12_;
			_tmp12_ = g_error_new_literal (SKK_RULE_PARSE_ERROR, SKK_RULE_PARSE_ERROR_FAILED, "metadata must be a JSON object");
			_inner_error_ = _tmp12_;
			__vala_JsonNode_free0 (root);
			goto __catch24_g_error;
		}
		_tmp13_ = root;
		_tmp14_ = json_node_get_object (_tmp13_);
		_tmp15_ = __vala_JsonObject_copy0 (_tmp14_);
		object = _tmp15_;
		_tmp16_ = object;
		_tmp17_ = json_object_has_member (_tmp16_, "name");
		if (!_tmp17_) {
			GError* _tmp18_;
			_tmp18_ = g_error_new_literal (SKK_RULE_PARSE_ERROR, SKK_RULE_PARSE_ERROR_FAILED, "name is not defined in metadata");
			_inner_error_ = _tmp18_;
			__vala_JsonNode_free0 (member);
			__vala_JsonObject_free0 (object);
			__vala_JsonNode_free0 (root);
			goto __catch24_g_error;
		}
		_tmp19_ = object;
		_tmp20_ = json_object_get_member (_tmp19_, "name");
		_tmp21_ = __vala_JsonNode_copy0 (_tmp20_);
		__vala_JsonNode_free0 (member);
		member = _tmp21_;
		_tmp22_ = member;
		_tmp23_ = json_node_get_string (_tmp22_);
		_tmp24_ = g_strdup (_tmp23_);
		name = _tmp24_;
		_tmp25_ = object;
		_tmp26_ = json_object_has_member (_tmp25_, "description");
		if (!_tmp26_) {
			GError* _tmp27_;
			_tmp27_ = g_error_new_literal (SKK_RULE_PARSE_ERROR, SKK_RULE_PARSE_ERROR_FAILED, "description is not defined in metadata");
			_inner_error_ = _tmp27_;
			_g_free0 (name);
			__vala_JsonNode_free0 (member);
			__vala_JsonObject_free0 (object);
			__vala_JsonNode_free0 (root);
			goto __catch24_g_error;
		}
		_tmp28_ = object;
		_tmp29_ = json_object_get_member (_tmp28_, "description");
		_tmp30_ = __vala_JsonNode_copy0 (_tmp29_);
		__vala_JsonNode_free0 (member);
		member = _tmp30_;
		_tmp31_ = member;
		_tmp32_ = json_node_get_string (_tmp31_);
		_tmp33_ = g_strdup (_tmp32_);
		description = _tmp33_;
		_tmp34_ = object;
		_tmp35_ = json_object_has_member (_tmp34_, "filter");
		if (_tmp35_) {
			JsonObject* _tmp36_;
			JsonNode* _tmp37_ = NULL;
			JsonNode* _tmp38_;
			JsonNode* _tmp39_;
			const gchar* _tmp40_ = NULL;
			gchar* _tmp41_;
			GeeMap* _tmp42_;
			const gchar* _tmp43_;
			gboolean _tmp44_ = FALSE;
			_tmp36_ = object;
			_tmp37_ = json_object_get_member (_tmp36_, "filter");
			_tmp38_ = __vala_JsonNode_copy0 (_tmp37_);
			__vala_JsonNode_free0 (member);
			member = _tmp38_;
			_tmp39_ = member;
			_tmp40_ = json_node_get_string (_tmp39_);
			_tmp41_ = g_strdup (_tmp40_);
			_g_free0 (filter);
			filter = _tmp41_;
			_tmp42_ = skk_rule_filter_types;
			_tmp43_ = filter;
			_tmp44_ = gee_map_has_key (_tmp42_, _tmp43_);
			if (!_tmp44_) {
				const gchar* _tmp45_;
				GError* _tmp46_;
				_tmp45_ = filter;
				_tmp46_ = g_error_new (SKK_RULE_PARSE_ERROR, SKK_RULE_PARSE_ERROR_FAILED, "unknown filter type %s", _tmp45_);
				_inner_error_ = _tmp46_;
				_g_free0 (filter);
				_g_free0 (description);
				_g_free0 (name);
				__vala_JsonNode_free0 (member);
				__vala_JsonObject_free0 (object);
				__vala_JsonNode_free0 (root);
				goto __catch24_g_error;
			}
		} else {
			gchar* _tmp47_;
			_tmp47_ = g_strdup ("simple");
			_g_free0 (filter);
			filter = _tmp47_;
		}
		_tmp48_ = name;
		_tmp49_ = g_strdup (_tmp48_);
		_tmp50_ = description;
		_tmp51_ = g_strdup (_tmp50_);
		_tmp52_ = filter;
		_tmp53_ = g_strdup (_tmp52_);
		_tmp54_ = filename;
		_tmp55_ = g_path_get_dirname (_tmp54_);
		memset (&_tmp56_, 0, sizeof (SkkRuleMetadata));
		_g_free0 (_tmp56_.label);
		_tmp56_.label = _tmp49_;
		_g_free0 (_tmp56_.description);
		_tmp56_.description = _tmp51_;
		_g_free0 (_tmp56_.filter);
		_tmp56_.filter = _tmp53_;
		_g_free0 (_tmp56_.base_dir);
		_tmp56_.base_dir = _tmp55_;
		*result = _tmp56_;
		_g_free0 (filter);
		_g_free0 (description);
		_g_free0 (name);
		__vala_JsonNode_free0 (member);
		__vala_JsonObject_free0 (object);
		__vala_JsonNode_free0 (root);
		_g_object_unref0 (parser);
		return;
	}
	goto __finally24;
	__catch24_g_error:
	{
		GError* e = NULL;
		GError* _tmp57_;
		const gchar* _tmp58_;
		GError* _tmp59_;
		e = _inner_error_;
		_inner_error_ = NULL;
		_tmp57_ = e;
		_tmp58_ = _tmp57_->message;
		_tmp59_ = g_error_new (SKK_RULE_PARSE_ERROR, SKK_RULE_PARSE_ERROR_FAILED, "can't load rule: %s", _tmp58_);
		_inner_error_ = _tmp59_;
		_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) {
		GeeMap* _tmp1_;
		SkkRuleMetadata _tmp2_;
		const gchar* _tmp3_;
		gpointer _tmp4_ = NULL;
		GType* type;
		GType* _tmp5_;
		GObject* _tmp6_ = NULL;
		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;
	const gchar* _tmp0_;
	SkkRuleMetadata* _tmp1_ = NULL;
	SkkRuleMetadata* metadata;
	SkkRuleMetadata* _tmp2_;
	SkkRuleMetadata* _tmp5_;
	SkkRuleMetadata* _tmp6_ = NULL;
	SkkRuleMetadata* default_metadata;
	SkkRuleMetadata* _tmp27_;
	gchar* _tmp28_ = NULL;
	gchar* _tmp29_;
	gboolean _tmp30_;
	SkkRuleMetadata _tmp33_;
	SkkRomKanaMapFile* _tmp34_;
	SkkRomKanaMapFile* _tmp35_;
	GError * _inner_error_ = NULL;
	g_return_val_if_fail (name != NULL, NULL);
	self = (SkkRule*) g_object_new (object_type, NULL);
	_tmp0_ = name;
	_tmp1_ = skk_rule_find_rule (_tmp0_);
	metadata = _tmp1_;
	_tmp2_ = metadata;
	if (_tmp2_ == NULL) {
		const gchar* _tmp3_;
		GError* _tmp4_;
		_tmp3_ = name;
		_tmp4_ = g_error_new (SKK_RULE_PARSE_ERROR, SKK_RULE_PARSE_ERROR_FAILED, "can't find metadata for \"%s\"", _tmp3_);
		_inner_error_ = _tmp4_;
		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;
		}
	}
	_tmp5_ = metadata;
	skk_rule_set_metadata (self, _tmp5_);
	_tmp6_ = skk_rule_find_rule ("default");
	default_metadata = _tmp6_;
	{
		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* _tmp7_;
				SkkRuleMetadata* _tmp8_;
				SkkRuleMetadata* _metadata;
				SkkRuleMetadata* _tmp9_;
				SkkRuleKeymapNameEntry _tmp10_;
				const gchar* _tmp11_;
				gchar* _tmp12_ = NULL;
				gchar* _tmp13_;
				gboolean _tmp14_;
				SkkRuleMetadata* _tmp17_;
				SkkRuleKeymapNameEntry _tmp18_;
				const gchar* _tmp19_;
				SkkRuleMetadata _tmp20_;
				SkkKeymapMapFile* _tmp21_;
				SkkKeymapMapFile* _tmp22_;
				SkkKeymapMapFile** _tmp23_;
				gint _tmp23__length1;
				SkkRuleKeymapNameEntry _tmp24_;
				SkkInputMode _tmp25_;
				SkkKeymapMapFile* _tmp26_;
				_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_;
				}
				_tmp17_ = _metadata;
				_tmp18_ = entry;
				_tmp19_ = _tmp18_.value;
				_tmp20_ = *_tmp17_;
				_tmp21_ = skk_keymap_map_file_new (&_tmp20_, _tmp19_, &_inner_error_);
				_tmp22_ = _tmp21_;
				if (_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;
				_g_object_unref0 (_tmp23_[_tmp25_]);
				_tmp23_[_tmp25_] = _tmp22_;
				_tmp26_ = _tmp23_[_tmp25_];
				_skk_rule_metadata_free0 (_metadata);
			}
		}
	}
	_tmp27_ = metadata;
	_tmp28_ = skk_rule_metadata_locate_map_file (_tmp27_, "rom-kana", "default");
	_tmp29_ = _tmp28_;
	_tmp30_ = _tmp29_ == NULL;
	_g_free0 (_tmp29_);
	if (_tmp30_) {
		SkkRuleMetadata* _tmp31_;
		SkkRuleMetadata _tmp32_ = {0};
		_tmp31_ = default_metadata;
		skk_rule_metadata_copy (_tmp31_, &_tmp32_);
		skk_rule_metadata_destroy (&self->priv->_metadata);
		self->priv->_metadata = _tmp32_;
	}
	_tmp33_ = self->priv->_metadata;
	_tmp34_ = skk_rom_kana_map_file_new (&_tmp33_, &_inner_error_);
	_tmp35_ = _tmp34_;
	if (_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;
		}
	}
	_g_object_unref0 (self->rom_kana);
	self->rom_kana = _tmp35_;
	_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_;
	const gchar* _tmp1_;
	gboolean _tmp2_ = FALSE;
	gchar** _tmp6_;
	gint _tmp6__length1;
	GError * _inner_error_ = NULL;
	g_return_val_if_fail (name != NULL, NULL);
	_tmp0_ = skk_rule_rule_cache;
	_tmp1_ = name;
	_tmp2_ = gee_map_has_key (_tmp0_, _tmp1_);
	if (_tmp2_) {
		GeeMap* _tmp3_;
		const gchar* _tmp4_;
		gpointer _tmp5_ = NULL;
		_tmp3_ = skk_rule_rule_cache;
		_tmp4_ = name;
		_tmp5_ = gee_map_get (_tmp3_, _tmp4_);
		result = (SkkRuleMetadata*) _tmp5_;
		return result;
	}
	_tmp6_ = skk_rule_rules_path;
	_tmp6__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 = _tmp6_;
		dir_collection_length1 = _tmp6__length1;
		for (dir_it = 0; dir_it < _tmp6__length1; dir_it = dir_it + 1) {
			gchar* _tmp7_;
			gchar* dir = NULL;
			_tmp7_ = g_strdup (dir_collection[dir_it]);
			dir = _tmp7_;
			{
				const gchar* _tmp8_;
				const gchar* _tmp9_;
				gchar* _tmp10_ = NULL;
				gchar* base_dir_filename;
				const gchar* _tmp11_;
				gchar* _tmp12_ = NULL;
				gchar* metadata_filename;
				const gchar* _tmp13_;
				gboolean _tmp14_ = FALSE;
				_tmp8_ = dir;
				_tmp9_ = name;
				_tmp10_ = g_build_filename (_tmp8_, _tmp9_, NULL);
				base_dir_filename = _tmp10_;
				_tmp11_ = base_dir_filename;
				_tmp12_ = g_build_filename (_tmp11_, "metadata.json", NULL);
				metadata_filename = _tmp12_;
				_tmp13_ = metadata_filename;
				_tmp14_ = g_file_test (_tmp13_, G_FILE_TEST_EXISTS);
				if (_tmp14_) {
					{
						const gchar* _tmp15_;
						SkkRuleMetadata _tmp16_ = {0};
						SkkRuleMetadata metadata;
						const gchar* _tmp17_;
						gchar* _tmp18_;
						GeeMap* _tmp19_;
						const gchar* _tmp20_;
						SkkRuleMetadata _tmp21_;
						SkkRuleMetadata _tmp22_;
						SkkRuleMetadata* _tmp23_;
						SkkRuleMetadata* _tmp24_;
						_tmp15_ = metadata_filename;
						skk_rule_load_metadata (_tmp15_, &_tmp16_, &_inner_error_);
						metadata = _tmp16_;
						if (_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;
						}
						_tmp17_ = name;
						_tmp18_ = g_strdup (_tmp17_);
						_g_free0 (metadata.name);
						metadata.name = _tmp18_;
						_tmp19_ = skk_rule_rule_cache;
						_tmp20_ = name;
						_tmp21_ = metadata;
						gee_map_set (_tmp19_, _tmp20_, &_tmp21_);
						_tmp22_ = metadata;
						_tmp23_ = _skk_rule_metadata_dup0 (&_tmp22_);
						_tmp24_ = _tmp23_;
						skk_rule_metadata_destroy (&_tmp22_);
						result = _tmp24_;
						_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;
	GeeHashSet* _tmp0_;
	GeeSet* names;
	SkkRuleMetadata* _tmp1_ = NULL;
	SkkRuleMetadata* rules;
	gint rules_length1;
	gint _rules_size_;
	gchar** _tmp2_;
	gint _tmp2__length1;
	SkkRuleMetadata* _tmp31_;
	gint _tmp31__length1;
	GError * _inner_error_ = NULL;
	_tmp0_ = gee_hash_set_new (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, g_free, 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;
				{
					const gchar* _tmp4_;
					GDir* _tmp5_ = NULL;
					GDir* _tmp6_;
					_tmp4_ = dir;
					_tmp5_ = g_dir_open (_tmp4_, (guint) 0, &_inner_error_);
					_tmp6_ = _tmp5_;
					if (_inner_error_ != NULL) {
						goto __catch26_g_error;
					}
					_g_dir_close0 (handle);
					handle = _tmp6_;
				}
				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 (_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* _tmp7_;
					const gchar* _tmp8_ = NULL;
					gchar* _tmp9_;
					const gchar* _tmp10_;
					GeeSet* _tmp11_;
					const gchar* _tmp12_;
					gboolean _tmp13_ = FALSE;
					const gchar* _tmp14_;
					const gchar* _tmp15_;
					gchar* _tmp16_ = NULL;
					gchar* metadata_filename;
					const gchar* _tmp17_;
					gboolean _tmp18_ = FALSE;
					_tmp7_ = handle;
					_tmp8_ = g_dir_read_name (_tmp7_);
					_tmp9_ = g_strdup (_tmp8_);
					_g_free0 (name);
					name = _tmp9_;
					_tmp10_ = name;
					if (!(_tmp10_ != NULL)) {
						break;
					}
					_tmp11_ = names;
					_tmp12_ = name;
					_tmp13_ = gee_collection_contains ((GeeCollection*) _tmp11_, _tmp12_);
					if (_tmp13_) {
						continue;
					}
					_tmp14_ = dir;
					_tmp15_ = name;
					_tmp16_ = g_build_filename (_tmp14_, _tmp15_, "metadata.json", NULL);
					metadata_filename = _tmp16_;
					_tmp17_ = metadata_filename;
					_tmp18_ = g_file_test (_tmp17_, G_FILE_TEST_EXISTS);
					if (_tmp18_) {
						{
							const gchar* _tmp19_;
							SkkRuleMetadata _tmp20_ = {0};
							SkkRuleMetadata metadata;
							GeeSet* _tmp21_;
							const gchar* _tmp22_;
							const gchar* _tmp23_;
							gchar* _tmp24_;
							SkkRuleMetadata* _tmp25_;
							gint _tmp25__length1;
							SkkRuleMetadata _tmp26_;
							SkkRuleMetadata _tmp27_ = {0};
							_tmp19_ = metadata_filename;
							skk_rule_load_metadata (_tmp19_, &_tmp20_, &_inner_error_);
							metadata = _tmp20_;
							if (_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;
							}
							_tmp21_ = names;
							_tmp22_ = name;
							gee_collection_add ((GeeCollection*) _tmp21_, _tmp22_);
							_tmp23_ = name;
							_tmp24_ = g_strdup (_tmp23_);
							_g_free0 (metadata.name);
							metadata.name = _tmp24_;
							_tmp25_ = rules;
							_tmp25__length1 = rules_length1;
							_tmp26_ = metadata;
							skk_rule_metadata_copy (&_tmp26_, &_tmp27_);
							_vala_array_add1 (&rules, &rules_length1, &_rules_size_, &_tmp27_);
							skk_rule_metadata_destroy (&metadata);
						}
						goto __finally27;
						__catch27_skk_rule_parse_error:
						{
							GError* e = NULL;
							const gchar* _tmp28_;
							GError* _tmp29_;
							const gchar* _tmp30_;
							e = _inner_error_;
							_inner_error_ = NULL;
							_tmp28_ = metadata_filename;
							_tmp29_ = e;
							_tmp30_ = _tmp29_->message;
							g_warning ("rule.vala:346: can't load metadata %s: %s", _tmp28_, _tmp30_);
							_g_error_free0 (e);
						}
						__finally27:
						if (_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);
			}
		}
	}
	_tmp31_ = rules;
	_tmp31__length1 = rules_length1;
	if (result_length1) {
		*result_length1 = _tmp31__length1;
	}
	result = _tmp31_;
	_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 void skk_rule_set_metadata (SkkRule* self, SkkRuleMetadata* value) {
	SkkRuleMetadata _tmp0_;
	SkkRuleMetadata _tmp1_ = {0};
	g_return_if_fail (self != NULL);
	_tmp0_ = *value;
	skk_rule_metadata_copy (&_tmp0_, &_tmp1_);
	skk_rule_metadata_destroy (&self->priv->_metadata);
	self->priv->_metadata = _tmp1_;
	g_object_notify ((GObject *) self, "metadata");
}


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_ = 0;
	gchar** _tmp3_ = NULL;
	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, g_param_spec_boxed ("metadata", "metadata", "metadata", SKK_TYPE_RULE_METADATA, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
	_tmp0_ = gee_hash_map_new (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, g_free, G_TYPE_GTYPE, (GBoxedCopyFunc) _g_type_dup, g_free, NULL, NULL, NULL);
	skk_rule_filter_types = (GeeMap*) _tmp0_;
	_tmp1_ = gee_hash_map_new (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, g_free, SKK_TYPE_RULE_METADATA, (GBoxedCopyFunc) skk_rule_metadata_dup, skk_rule_metadata_free, 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_ = NULL;
	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:
		{
			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:
		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);
}



