5f5d00c441ae0ef349c68b273e6c86e6ec2cf4cf
[yazpp-moved-to-github.git] / src / yaz-ir-assoc.cpp
1 /*
2  * Copyright (c) 1998-2003, Index Data.
3  * See the file LICENSE for details.
4  * 
5  * $Id: yaz-ir-assoc.cpp,v 1.27 2006-03-29 13:14:15 adam Exp $
6  */
7
8 #include <assert.h>
9
10 #include <yaz/log.h>
11 #include <yazpp/ir-assoc.h>
12
13 using namespace yazpp_1;
14
15 IR_Assoc::IR_Assoc(IPDU_Observable *the_PDU_Observable)
16     : Z_Assoc(the_PDU_Observable)
17 {
18     m_num_databaseNames = 0;
19     m_databaseNames = 0;
20     m_preferredRecordSyntax = VAL_NONE;
21     m_elementSetNames = 0;
22     m_lastReceived = 0;
23     m_host = 0;
24     m_proxy = 0;
25     m_cookie = 0;
26     m_log = YLOG_DEBUG;
27     const char *db = "Default";
28     set_databaseNames(1, &db);
29 }
30
31 IR_Assoc::~IR_Assoc()
32 {
33     if (m_elementSetNames)
34         delete [] m_elementSetNames->u.generic;
35     delete [] m_elementSetNames;
36     delete [] m_host;
37     delete [] m_proxy;
38     delete [] m_cookie;
39 }
40
41 void IR_Assoc::get_databaseNames (int *num, char ***list)
42 {
43     *num = m_num_databaseNames;
44     *list = m_databaseNames;
45 }
46
47 typedef char *charp;
48 void IR_Assoc::set_databaseNames (int num, const char **list)
49 {
50     int i;
51     yaz_log (m_log, "IR_Assoc::set_databaseNames num=%d", num);
52     for (i = 0; i<m_num_databaseNames; i++)
53         delete [] m_databaseNames[i];
54     delete [] m_databaseNames;
55     m_num_databaseNames = num;
56
57     m_databaseNames = new char *[num];
58     for (i = 0; i<m_num_databaseNames; i++)
59     {
60         m_databaseNames[i] = new char[strlen(list[i])+1];
61         strcpy(m_databaseNames[i], list[i]);
62     }
63 }
64
65 void IR_Assoc::set_databaseNames(const char *dblist, const char *sep)
66 {
67     const char **list = new const char* [strlen(dblist)];
68     char *dbtmp = new char[strlen(dblist)+1];
69     strcpy(dbtmp, dblist);
70     int num = 0;
71     int len = 0;
72     for (char *cp = dbtmp; ; cp++)
73         if (*cp && !strchr(sep, *cp))
74             len++;
75         else
76         {
77             if (len)
78             {
79                 list[num] = cp - len;
80                 num++;
81             }
82             if (!*cp)
83                 break;
84             *cp = '\0';
85             len = 0;
86         }
87     set_databaseNames (num, list);
88     delete [] dbtmp;
89     delete [] list;
90 }
91
92 void IR_Assoc::set_preferredRecordSyntax (int value)
93 {
94     m_preferredRecordSyntax = value;
95 }
96
97 void IR_Assoc::set_preferredRecordSyntax (const char *syntax)
98 {
99     m_preferredRecordSyntax = VAL_NONE;
100     if (syntax && *syntax)
101         m_preferredRecordSyntax = oid_getvalbyname (syntax);
102 }
103
104 void IR_Assoc::get_preferredRecordSyntax (int *value)
105 {
106     *value = m_preferredRecordSyntax;
107 }
108
109 void IR_Assoc::get_preferredRecordSyntax (const char **dst)
110 {
111     struct oident ent;
112     ent.proto = PROTO_Z3950;
113     ent.oclass = CLASS_RECSYN;
114     ent.value = (enum oid_value) m_preferredRecordSyntax;
115
116     int oid[OID_SIZE];
117     oid_ent_to_oid (&ent, oid);
118     struct oident *entp = oid_getentbyoid (oid);
119     
120     *dst = entp ? entp->desc : "";
121 }
122
123 void IR_Assoc::set_elementSetName (const char *elementSetName)
124 {
125     if (m_elementSetNames)
126         delete [] m_elementSetNames->u.generic;
127     delete m_elementSetNames;
128     m_elementSetNames = 0;
129     if (elementSetName && *elementSetName)
130     {
131         m_elementSetNames = new Z_ElementSetNames;
132         m_elementSetNames->which = Z_ElementSetNames_generic;
133         m_elementSetNames->u.generic = new char[strlen(elementSetName)+1];
134         strcpy (m_elementSetNames->u.generic, elementSetName);
135     }
136 }
137
138 void IR_Assoc::get_elementSetName (Z_ElementSetNames **elementSetNames)
139 {
140     *elementSetNames = m_elementSetNames;
141 }
142
143 void IR_Assoc::get_elementSetName (const char **elementSetName)
144 {
145     if (!m_elementSetNames ||
146         m_elementSetNames->which != Z_ElementSetNames_generic)
147     {
148         *elementSetName = 0;
149         return;
150     }
151     *elementSetName = m_elementSetNames->u.generic;
152 }
153
154
155 void IR_Assoc::recv_GDU(Z_GDU *apdu, int len)
156 {
157     if (apdu->which == Z_GDU_Z3950)
158             recv_Z_PDU(apdu->u.z3950, len);
159 }
160
161 void IR_Assoc::recv_Z_PDU(Z_APDU *apdu, int len)
162 {
163     yaz_log (m_log, "recv_Z_PDU %d bytes", len);
164     m_lastReceived = apdu->which;
165     switch (apdu->which)
166     {
167     case Z_APDU_initResponse:
168         yaz_log (m_log, "recv InitResponse");
169         recv_initResponse(apdu->u.initResponse);
170         break;
171     case Z_APDU_initRequest:
172         yaz_log (m_log, "recv InitRequest");
173         recv_initRequest(apdu->u.initRequest);
174         break;
175     case Z_APDU_searchRequest:
176         yaz_log (m_log, "recv searchRequest");
177         recv_searchRequest(apdu->u.searchRequest);
178         break;
179     case Z_APDU_searchResponse:
180         yaz_log (m_log, "recv searchResponse"); 
181         recv_searchResponse(apdu->u.searchResponse);
182         break;
183     case Z_APDU_presentRequest:
184         yaz_log (m_log, "recv presentRequest");
185         recv_presentRequest(apdu->u.presentRequest);
186         break;
187     case Z_APDU_presentResponse:
188         yaz_log (m_log, "recv presentResponse");
189         recv_presentResponse(apdu->u.presentResponse);
190         break;
191     case Z_APDU_extendedServicesResponse:
192         yaz_log (m_log, "recv extendedServiceResponse");
193         recv_extendedServicesResponse(apdu->u.extendedServicesResponse);
194         break;
195     }
196 }
197
198 int IR_Assoc::send_searchRequest(Yaz_Z_Query *query,
199                                      char* pResultSetId,
200                                      char* pRefId)
201 {
202     Z_APDU *apdu = create_Z_PDU(Z_APDU_searchRequest);
203     Z_SearchRequest *req = apdu->u.searchRequest;
204     int recordSyntax;
205
206     req->query = query->get_Z_Query();
207     if (!req->query)
208         return -1;
209     get_databaseNames (&req->num_databaseNames, &req->databaseNames);
210     int oid_syntax[OID_SIZE];
211     oident prefsyn;
212     get_preferredRecordSyntax(&recordSyntax);
213     if (recordSyntax != VAL_NONE)
214     {
215         prefsyn.proto = PROTO_Z3950;
216         prefsyn.oclass = CLASS_RECSYN;
217         prefsyn.value = (enum oid_value) recordSyntax;
218         oid_ent_to_oid(&prefsyn, oid_syntax);
219         req->preferredRecordSyntax = oid_syntax;
220     }
221     yaz_log (m_log, "send_searchRequest");
222     assert (req->otherInfo == 0);
223     if (m_cookie)
224     {
225         set_otherInformationString(&req->otherInfo, VAL_COOKIE, 1, m_cookie);
226         assert (req->otherInfo);
227     }
228
229     if ( pRefId )
230     {
231         req->referenceId = getRefID(pRefId);
232     }
233
234     if ( pResultSetId )
235     {
236         req->resultSetName = pResultSetId;
237     }
238
239     return send_Z_PDU(apdu, 0);
240 }
241
242 int IR_Assoc::send_presentRequest(int start, 
243                                       int number, 
244                                       char* pResultSetId,
245                                       char* pRefId)
246 {
247     Z_APDU *apdu = create_Z_PDU(Z_APDU_presentRequest);
248     Z_PresentRequest *req = apdu->u.presentRequest;
249
250     req->resultSetStartPoint = &start;
251     req->numberOfRecordsRequested = &number;
252
253     int oid_syntax[OID_SIZE];
254     oident prefsyn;
255     int recordSyntax;
256     get_preferredRecordSyntax (&recordSyntax);
257     if (recordSyntax != VAL_NONE)
258     {
259         prefsyn.proto = PROTO_Z3950;
260         prefsyn.oclass = CLASS_RECSYN;
261         prefsyn.value = (enum oid_value) recordSyntax;
262         oid_ent_to_oid(&prefsyn, oid_syntax);
263         req->preferredRecordSyntax = oid_syntax;
264     }
265     Z_RecordComposition compo;
266     Z_ElementSetNames *elementSetNames;
267     get_elementSetName (&elementSetNames);
268     if (elementSetNames)
269     {
270         req->recordComposition = &compo;
271         compo.which = Z_RecordComp_simple;
272         compo.u.simple = elementSetNames;
273     }
274
275     if (m_cookie)
276         set_otherInformationString(&req->otherInfo, VAL_COOKIE, 1, m_cookie);
277
278     if ( pRefId )
279     {
280         req->referenceId = getRefID(pRefId);
281     }
282
283     if ( pResultSetId )
284     {
285         req->resultSetId = pResultSetId;
286     }
287
288     return send_Z_PDU(apdu, 0);
289 }
290
291 void IR_Assoc::set_proxy(const char *str)
292 {
293     delete [] m_proxy;
294     m_proxy = 0;
295     if (str)
296     {
297         m_proxy = new char[strlen(str)+1];
298         strcpy (m_proxy, str);
299     }
300 }
301
302 void IR_Assoc::set_cookie(const char *str)
303 {
304     delete [] m_cookie;
305     m_cookie = 0;
306     if (str)
307     {
308         m_cookie = new char[strlen(str)+1];
309         strcpy(m_cookie, str);
310     }
311 }
312
313 const char *IR_Assoc::get_cookie()
314 {
315     return m_cookie;
316 }
317
318 void IR_Assoc::client(const char *addr)
319 {
320     delete [] m_host;
321     m_host = new char[strlen(addr)+1];
322     strcpy(m_host, addr);
323     const char *dbpart = strchr(m_host, '/');
324     if (dbpart)
325         set_databaseNames (dbpart+1, "+ ");
326     Z_Assoc::client(m_proxy ? m_proxy : m_host);
327 }
328
329 const char *IR_Assoc::get_proxy()
330 {
331     return m_proxy;
332 }
333
334 const char *IR_Assoc::get_host()
335 {
336     return m_host;
337 }
338
339 void IR_Assoc::recv_searchRequest(Z_SearchRequest *searchRequest)
340 {
341     Z_APDU *apdu = create_Z_PDU(Z_APDU_searchResponse);
342     send_Z_PDU(apdu, 0);
343 }
344
345 void IR_Assoc::recv_presentRequest(Z_PresentRequest *presentRequest)
346 {
347     Z_APDU *apdu = create_Z_PDU(Z_APDU_presentResponse);
348     send_Z_PDU(apdu, 0);
349 }
350
351 void IR_Assoc::recv_initRequest(Z_InitRequest *initRequest)
352 {
353     Z_APDU *apdu = create_Z_PDU(Z_APDU_initResponse);
354     send_Z_PDU(apdu, 0);
355 }
356
357 void IR_Assoc::recv_searchResponse (Z_SearchResponse *searchResponse)
358 {
359 }
360
361 void IR_Assoc::recv_presentResponse (Z_PresentResponse *presentResponse)
362 {
363 }
364
365 void IR_Assoc::recv_initResponse(Z_InitResponse *initResponse)
366 {
367 }
368
369 void IR_Assoc::recv_extendedServicesResponse(Z_ExtendedServicesResponse *ExtendedServicesResponse)
370 {
371 }
372
373 int IR_Assoc::get_lastReceived()
374 {
375     return m_lastReceived;
376 }
377
378 void IR_Assoc::set_lastReceived(int lastReceived)
379 {
380     m_lastReceived = lastReceived;
381 }
382
383 int IR_Assoc::send_initRequest(char* pRefId)
384 {
385     Z_APDU *apdu = create_Z_PDU(Z_APDU_initRequest);
386     Z_InitRequest *req = apdu->u.initRequest;
387     
388     ODR_MASK_SET(req->options, Z_Options_search);
389     ODR_MASK_SET(req->options, Z_Options_present);
390     ODR_MASK_SET(req->options, Z_Options_namedResultSets);
391     ODR_MASK_SET(req->options, Z_Options_triggerResourceCtrl);
392     ODR_MASK_SET(req->options, Z_Options_scan);
393     ODR_MASK_SET(req->options, Z_Options_sort);
394     ODR_MASK_SET(req->options, Z_Options_extendedServices);
395     ODR_MASK_SET(req->options, Z_Options_delSet);
396
397     ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_1);
398     ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_2);
399     ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_3);
400
401     if ( pRefId )
402     {
403         req->referenceId = getRefID(pRefId);
404     }
405
406     if (m_proxy && m_host)
407         set_otherInformationString(&req->otherInfo, VAL_PROXY, 1, m_host);
408     if (m_cookie)
409         set_otherInformationString(&req->otherInfo, VAL_COOKIE, 1, m_cookie);
410     return send_Z_PDU(apdu, 0);
411 }
412
413 int IR_Assoc::send_deleteResultSetRequest(char* pResultSetId, char* pRefId)
414 {
415     char* ResultSetIds[1];
416
417     Z_APDU *apdu = create_Z_PDU(Z_APDU_deleteResultSetRequest);
418     Z_DeleteResultSetRequest *req = apdu->u.deleteResultSetRequest;
419
420     if ( pResultSetId )
421     {
422         *req->deleteFunction = Z_DeleteResultSetRequest_list;
423         req->num_resultSetList = 1;
424         ResultSetIds[0] = pResultSetId;
425         req->resultSetList = ResultSetIds;
426     }
427     else
428     {
429         *req->deleteFunction = Z_DeleteResultSetRequest_all;
430     }
431     
432     if ( pRefId )
433     {
434         req->referenceId = getRefID(pRefId);
435     }
436
437     if (m_proxy && m_host)
438         set_otherInformationString(&req->otherInfo, VAL_PROXY, 1, m_host);
439     if (m_cookie)
440         set_otherInformationString(&req->otherInfo, VAL_COOKIE, 1, m_cookie);
441
442     return send_Z_PDU(apdu, 0);
443 }
444
445
446 /*
447  * Local variables:
448  * c-basic-offset: 4
449  * indent-tabs-mode: nil
450  * End:
451  * vim: shiftwidth=4 tabstop=8 expandtab
452  */
453