+struct pp2_charset_fact_s {
+ struct pp2_charset_entry *list;
+ int ref_count;
+};
+
+struct pp2_charset_entry {
+ struct pp2_charset_entry *next;
+ pp2_charset_t pct;
+ char *name;
+};
+
+
+static int pp2_charset_fact_add(pp2_charset_fact_t pft,
+ pp2_charset_t pct, const char *default_id);
+
+pp2_charset_fact_t pp2_charset_fact_create(void)
+{
+ pp2_charset_fact_t pft = xmalloc(sizeof(*pft));
+ pft->list = 0;
+ pft->ref_count = 1;
+
+ pp2_charset_fact_add(pft, pp2_charset_create_a_to_z(), "relevance");
+ pp2_charset_fact_add(pft, pp2_charset_create_a_to_z(), "sort");
+ pp2_charset_fact_add(pft, pp2_charset_create_a_to_z(), "mergekey");
+ pp2_charset_fact_add(pft, pp2_charset_create(), "facet");
+ return pft;
+}
+
+void pp2_charset_fact_destroy(pp2_charset_fact_t pft)
+{
+ if (pft)
+ {
+ assert(pft->ref_count >= 1);
+ --(pft->ref_count);
+ if (pft->ref_count == 0)
+ {
+ struct pp2_charset_entry *pce = pft->list;
+ while (pce)
+ {
+ struct pp2_charset_entry *next = pce->next;
+ pp2_charset_destroy(pce->pct);
+ xfree(pce->name);
+ xfree(pce);
+ pce = next;
+ }
+ xfree(pft);
+ }
+ }
+}
+
+int pp2_charset_fact_add(pp2_charset_fact_t pft,
+ pp2_charset_t pct, const char *default_id)
+{
+ struct pp2_charset_entry *pce;
+
+ for (pce = pft->list; pce; pce = pce->next)
+ if (!strcmp(default_id, pce->name))
+ break;
+
+ if (!pce)
+ {
+ pce = xmalloc(sizeof(*pce));
+ pce->name = xstrdup(default_id);
+ pce->next = pft->list;
+ pft->list = pce;
+ }
+ else
+ {
+ pp2_charset_destroy(pce->pct);
+ }
+ pce->pct = pct;
+ return 0;
+}
+
+int pp2_charset_fact_define(pp2_charset_fact_t pft,
+ xmlNode *xml_node, const char *id)
+{
+ int r;
+ pp2_charset_t pct;
+
+ assert(xml_node);
+
+ if (strcmp((const char *) xml_node->name, "icu_chain"))
+ {
+ yaz_log(YLOG_WARN, "Wrapper element <%s> deprecated", xml_node->name);
+ yaz_log(YLOG_LOG, "Use <icu_chain id=\"%s\">.. only", xml_node->name);
+ xml_node = xml_node->children;
+ while (xml_node && xml_node->type != XML_ELEMENT_NODE)
+ xml_node = xml_node->next;
+ }
+ if (!xml_node)
+ {
+ yaz_log(YLOG_FATAL, "Missing icu_chain element");
+ return -1;
+ }
+ pct = pp2_charset_create_xml(xml_node);
+ if (!pct)
+ return -1;
+ if (!id)
+ {
+ id = yaz_xml_get_prop(xml_node, "id");
+ if (!id)
+ {
+ yaz_log(YLOG_WARN, "Missing id for icu_chain");
+ pp2_charset_destroy(pct);
+ return -1;
+ }
+ }
+ r = pp2_charset_fact_add(pft, pct, id);
+ return r;
+}
+
+void pp2_charset_fact_incref(pp2_charset_fact_t pft)
+{
+ (pft->ref_count)++;
+}