IDZEBRA  2.1.2
d1_map.c
Go to the documentation of this file.
1 /* This file is part of the Zebra server.
2  Copyright (C) Index Data
3 
4 Zebra is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8 
9 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 
18 */
19 
20 #if HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include <yaz/log.h>
28 #include <yaz/oid_db.h>
29 #include <yaz/readconf.h>
30 #include <yaz/tpath.h>
31 #include <d1_absyn.h>
32 
34 {
35  int no_data;
36  int no_chop;
40 };
41 
43 {
44  NMEM mem = data1_nmem_get (dh);
45  data1_maptab *res = (data1_maptab *)nmem_malloc(mem, sizeof(*res));
46  FILE *f;
47  int lineno = 0;
48  int argc;
49  char *argv[50], line[512];
50  data1_mapunit **mapp;
51  int local_numeric = 0;
52 
53  if (!(f = data1_path_fopen(dh, file, "r")))
54  return 0;
55 
56  res->name = 0;
57  res->oid = 0;
58  res->map = 0;
59  mapp = &res->map;
60  res->next = 0;
61 
62  while ((argc = readconf_line(f, &lineno, line, 512, argv, 50)))
63  if (!strcmp(argv[0], "targetref"))
64  {
65  if (argc != 2)
66  {
67  yaz_log(YLOG_WARN, "%s:%d: Bad # args for targetref",
68  file, lineno);
69  continue;
70  }
71  res->oid = yaz_string_to_oid_nmem(yaz_oid_std(),
72  CLASS_RECSYN, argv[1], mem);
73  if (!res->oid)
74  {
75  yaz_log(YLOG_WARN, "%s:%d: Unknown reference '%s'",
76  file, lineno, argv[1]);
77  continue;
78  }
79  }
80  else if (!strcmp(argv[0], "targetname"))
81  {
82  if (argc != 2)
83  {
84  yaz_log(YLOG_WARN, "%s:%d: Bad # args for targetname",
85  file, lineno);
86  continue;
87  }
88  res->target_absyn_name =
89  (char *)nmem_malloc(mem, strlen(argv[1])+1);
90  strcpy(res->target_absyn_name, argv[1]);
91  }
92  else if (!yaz_matchstr(argv[0], "localnumeric"))
93  local_numeric = 1;
94  else if (!strcmp(argv[0], "name"))
95  {
96  if (argc != 2)
97  {
98  yaz_log(YLOG_WARN, "%s:%d: Bad # args for name", file, lineno);
99  continue;
100  }
101  res->name = (char *)nmem_malloc(mem, strlen(argv[1])+1);
102  strcpy(res->name, argv[1]);
103  }
104  else if (!strcmp(argv[0], "map"))
105  {
106  data1_maptag **mtp;
107  char *ep, *path = argv[2];
108 
109  if (argc < 3)
110  {
111  yaz_log(YLOG_WARN, "%s:%d: Bad # of args for map",
112  file, lineno);
113  continue;
114  }
115  *mapp = (data1_mapunit *)nmem_malloc(mem, sizeof(**mapp));
116  (*mapp)->next = 0;
117  if (argc > 3 && !data1_matchstr(argv[3], "nodata"))
118  (*mapp)->no_data = 1;
119  else
120  (*mapp)->no_data = 0;
121  if (argc > 3 && !data1_matchstr(argv[3], "nochop"))
122  (*mapp)->no_chop = 1;
123  else
124  (*mapp)->no_chop = 0;
125  (*mapp)->source_element_name =
126  (char *)nmem_malloc(mem, strlen(argv[1])+1);
127  strcpy((*mapp)->source_element_name, argv[1]);
128  mtp = &(*mapp)->target_path;
129  if (*path == '/')
130  path++;
131  for (ep = strchr(path, '/'); path; (void)((path = ep) &&
132  (ep = strchr(path, '/'))))
133  {
134  int type, np;
135  char valstr[512], parm[512];
136 
137  if (ep)
138  ep++;
139  if ((np = sscanf(path, "(%d,%511[^)]):%511[^/]", &type, valstr,
140  parm)) < 2)
141  {
142  yaz_log(YLOG_WARN, "%s:%d: Syntax error in map "
143  "directive: %s", file, lineno, argv[2]);
144  fclose(f);
145  return 0;
146  }
147  *mtp = (data1_maptag *)nmem_malloc(mem, sizeof(**mtp));
148  (*mtp)->next = 0;
149  (*mtp)->type = type;
150  if (np > 2 && !data1_matchstr(parm, "new"))
151  (*mtp)->new_field = 1;
152  else
153  (*mtp)->new_field = 0;
154  if ((type != 3 || local_numeric) && d1_isdigit(*valstr))
155  {
156  (*mtp)->which = D1_MAPTAG_numeric;
157  (*mtp)->value.numeric = atoi(valstr);
158  }
159  else
160  {
161  (*mtp)->which = D1_MAPTAG_string;
162  (*mtp)->value.string =
163  (char *)nmem_malloc(mem, strlen(valstr)+1);
164  strcpy((*mtp)->value.string, valstr);
165  }
166  mtp = &(*mtp)->next;
167  }
168  mapp = &(*mapp)->next;
169  }
170  else
171  yaz_log(YLOG_WARN, "%s:%d: Unknown directive '%s'",
172  file, lineno, argv[0]);
173 
174  fclose(f);
175  return res;
176 }
177 
178 /*
179  * See if the node n is equivalent to the tag t.
180  */
181 static int tagmatch(data1_node *n, data1_maptag *t)
182 {
183  if (n->which != DATA1N_tag)
184  return 0;
185  if (n->u.tag.element)
186  {
187  if (n->u.tag.element->tag->tagset)
188  {
189  if (n->u.tag.element->tag->tagset->type != t->type)
190  return 0;
191  }
192  else if (t->type != 3)
193  return 0;
194  if (n->u.tag.element->tag->which == DATA1T_numeric)
195  {
196  if (t->which != D1_MAPTAG_numeric)
197  return 0;
198  if (n->u.tag.element->tag->value.numeric != t->value.numeric)
199  return 0;
200  }
201  else
202  {
203  if (t->which != D1_MAPTAG_string)
204  return 0;
205  if (data1_matchstr(n->u.tag.element->tag->value.string,
206  t->value.string))
207  return 0;
208  }
209  }
210  else /* local tag */
211  {
212  char str[10];
213 
214  if (t->type != 3)
215  return 0;
216  if (t->which == D1_MAPTAG_numeric)
217  sprintf(str, "%d", t->value.numeric);
218  else
219  strcpy(str, t->value.string);
220  if (data1_matchstr(n->u.tag.tag, str))
221  return 0;
222  }
223  return 1;
224 }
225 
227  data1_node **last, NMEM mem,
228  data1_node *parent)
229 {
230  data1_node *first = 0;
231  data1_node **m = &first;
232 
233  for (; n; n = n->next)
234  {
235  *last = *m = (data1_node *) nmem_malloc (mem, sizeof(**m));
236  memcpy (*m, n, sizeof(**m));
237 
238  (*m)->parent = parent;
239  (*m)->root = parent->root;
240  (*m)->child = dup_child(dh, n->child, &(*m)->last_child, mem, *m);
241  m = &(*m)->next;
242  }
243  *m = 0;
244  return first;
245 }
246 
248  data1_node *res, NMEM mem)
249 {
250  data1_node *c;
251  data1_mapunit *m;
252  /*
253  * locate each source element in turn.
254  */
255  for (c = n->child; c; c = c->next)
256  if (c->which == DATA1N_tag && c->u.tag.element)
257  {
258  for (m = map->map; m; m = m->next)
259  {
261  c->u.tag.element->name))
262  {
263  data1_node *pn = res;
264  data1_node *cur = pn->last_child;
265  data1_maptag *mt;
266 
267  /*
268  * process the target path specification.
269  */
270  for (mt = m->target_path; mt; mt = mt->next)
271  {
272  if (!cur || mt->new_field || !tagmatch(cur, mt))
273  {
274  if (mt->which == D1_MAPTAG_string)
275  {
276  cur = data1_mk_node2 (dh, mem, DATA1N_tag, pn);
277  cur->u.tag.tag = mt->value.string;
278  }
279  else if (mt->which == D1_MAPTAG_numeric)
280  {
281  data1_tag *tag =
283  dh,
284  pn->root->u.root.absyn->tagset,
285  mt->type,
286  mt->value.numeric);
287 
288  if (tag && tag->names->name)
289  {
290  cur = data1_mk_tag (
291  dh, mem, tag->names->name, 0, pn);
292 
293  }
294  }
295  }
296 
297  if (mt->next)
298  pn = cur;
299  else if (!m->no_data)
300  {
301  cur->child =
302  dup_child (dh, c->child,
303  &cur->last_child, mem, cur);
304  if (!m->no_chop)
305  {
306  data1_concat_text(dh, mem, cur->child);
307  data1_chop_text(dh, mem, cur->child);
308  }
309  }
310  }
311  }
312  }
313  if (map_children(dh, c, map, res, mem) < 0)
314  return -1;
315  }
316  return 0;
317 }
318 
319 /*
320  * Create a (possibly lossy) copy of the given record based on the
321  * table. The new copy will refer back to the data of the original record,
322  * which should not be discarded during the lifetime of the copy.
323  */
325  data1_maptab *map, NMEM m)
326 {
327  data1_node *res1, *res = data1_mk_node2 (dh, m, DATA1N_root, 0);
328 
329  res->which = DATA1N_root;
330  res->u.root.type = map->target_absyn_name;
331  if (!(res->u.root.absyn = data1_get_absyn(dh, map->target_absyn_name,
333  {
334  yaz_log(YLOG_WARN, "%s: Failed to load target absyn '%s'",
335  map->name, map->target_absyn_name);
336  }
337  n = n->child;
338  if (!n)
339  return 0;
340  res1 = data1_mk_tag (dh, m, map->target_absyn_name, 0, res);
341  while (n && n->which != DATA1N_tag)
342  n = n->next;
343  if (map_children(dh, n, map, res1, m) < 0)
344  return 0;
345  return res;
346 }
347 
348 /*
349  * Local variables:
350  * c-basic-offset: 4
351  * c-file-style: "Stroustrup"
352  * indent-tabs-mode: nil
353  * End:
354  * vim: shiftwidth=4 tabstop=8 expandtab
355  */
356 
data1_tag * data1_gettagbynum(data1_handle dh, data1_tagset *s, int type, int value)
Definition: d1_tagset.c:64
#define DATA1N_tag
Definition: data1.h:276
data1_name * names
Definition: data1.h:203
char * name
Definition: data1.h:104
data1_absyn * data1_get_absyn(data1_handle dh, const char *name, enum DATA1_XPATH_INDEXING en)
Definition: d1_absyn.c:230
#define DATA1N_root
Definition: data1.h:274
struct data1_maptag * next
Definition: data1.h:97
int no_data
Definition: d1_map.c:35
int which
Definition: data1.h:91
data1_maptab * data1_read_maptab(data1_handle dh, const char *file)
Definition: d1_map.c:42
int new_field
Definition: data1.h:87
struct data1_mapunit * next
Definition: d1_map.c:39
#define data1_matchstr(s1, s2)
Definition: data1.h:36
struct data1_node * last_child
Definition: data1.h:342
static data1_node * dup_child(data1_handle dh, data1_node *n, data1_node **last, NMEM mem, data1_node *parent)
Definition: d1_map.c:226
char * source_element_name
Definition: d1_map.c:37
char * name
Definition: data1.h:114
FILE * data1_path_fopen(data1_handle dh, const char *file, const char *mode)
Definition: d1_handle.c:151
data1_node * data1_mk_tag(data1_handle dh, NMEM nmem, const char *tag, const char **attr, data1_node *at)
Definition: d1_read.c:294
int type
Definition: data1.h:88
#define d1_isdigit(c)
Definition: data1.h:32
int numeric
Definition: data1.h:94
#define D1_MAPTAG_numeric
Definition: data1.h:89
data1_maptag * target_path
Definition: d1_map.c:38
data1_node * data1_mk_node2(data1_handle dh, NMEM m, int type, data1_node *parent)
Definition: d1_read.c:145
data1_node * data1_map_record(data1_handle dh, data1_node *n, data1_maptab *map, NMEM m)
Definition: d1_map.c:324
char * tag
Definition: data1.h:296
union data1_node::@2 u
struct data1_node::@2::@3 root
static int map_children(data1_handle dh, data1_node *n, data1_maptab *map, data1_node *res, NMEM mem)
Definition: d1_map.c:247
struct data1_node * child
Definition: data1.h:341
char * string
Definition: data1.h:95
int no_chop
Definition: d1_map.c:36
int which
Definition: data1.h:285
Odr_oid * oid
Definition: data1.h:105
union data1_maptag::@0 value
data1_mapunit * map
Definition: data1.h:107
#define DATA1T_numeric
Definition: data1.h:204
struct data1_node * next
Definition: data1.h:340
static int tagmatch(data1_node *n, data1_maptag *t)
Definition: d1_map.c:181
NMEM data1_nmem_get(data1_handle dh)
Definition: d1_handle.c:66
char * target_absyn_name
Definition: data1.h:106
void data1_concat_text(data1_handle dh, NMEM m, data1_node *n)
Definition: d1_read.c:1137
struct data1_maptab * next
Definition: data1.h:108
void data1_chop_text(data1_handle dh, NMEM m, data1_node *n)
Definition: d1_read.c:1108
#define D1_MAPTAG_string
Definition: data1.h:90