1 /*
2  * Portions of this file Copyright 1999-2005 University of Chicago
3  * Portions of this file Copyright 1999-2005 The University of Southern California.
4  *
5  * This file or a portion of this file is licensed under the
6  * terms of the Globus Toolkit Public License, found at
7  * http://www.globus.org/toolkit/download/license.html.
8  * If you redistribute this file, with or without
9  * modifications, you must include this notice in the file.
10  */
11
12
13 #include "globus_soap_message.h"
14 #include "globus_i_soap_message.h"
15 #include "xsd_anyAttributes.h"
16
17 typedef struct
18 {
19     xsd_QName                           qname;
20     char *                              value;
21 } xsd_l_anyAttributes_element_t;
22
23 int
24 xsd_anyAttributes_size(
25     xsd_anyAttributes_t                 attrs)
26 0 {
27 0     return globus_hashtable_size(&attrs);
28 }
29
30 const char *
31 xsd_anyAttributes_lookup(
32     xsd_anyAttributes_t                 attrs,
33     xsd_QName *                         name)
34 0 {
35 0     xsd_l_anyAttributes_element_t *     element;
36
37 0     element = (xsd_l_anyAttributes_element_t *)
38         globus_hashtable_lookup(&attrs, name);
39 0     if(!element)
40     {
41 0         return NULL;
42     }
43
44 0     return element->value;
45 }
46
47 int
48 xsd_anyAttributes_insert(
49     xsd_anyAttributes_t                 attrs,
50     xsd_QName *                         name,
51     const char *                        value)
52 0 {
53 0     xsd_l_anyAttributes_element_t *     element;
54
55 0     element = (xsd_l_anyAttributes_element_t *)
56         globus_malloc(sizeof(xsd_l_anyAttributes_element_t));
57 0     xsd_QName_copy_contents(&element->qname, name);
58 0     element->value = globus_libc_strdup(value);
59
60 0     return globus_hashtable_insert(&attrs, &element->qname, element);
61 }
62
63 static
64 void
65 xsd_anyAttributes_element_delete(
66     void *                              value)
67 3324 {
68 3324     xsd_l_anyAttributes_element_t *     element;
69     
70 3324     element = (xsd_l_anyAttributes_element_t *) value;
71     
72 3324     if(element)
73     {
74 3324         xsd_QName_destroy_contents(&element->qname);
75 3324         if(element->value)
76         {
77 3324             globus_free(element->value);
78         }
79 3324         globus_free(element);
80     }
81 }
82
83 int
84 xsd_anyAttributes_remove(
85     xsd_anyAttributes_t                 attrs,
86     xsd_QName *                         name)
87 0 {
88 0     void *                              element;
89
90 0     element = globus_hashtable_remove(&attrs, name);
91 0     if(!element)
92     {
93 0         return GLOBUS_FAILURE;
94     }
95     
96 0     xsd_anyAttributes_element_delete(element);
97 0     return GLOBUS_SUCCESS;
98 }
99
100 void
101 xsd_anyAttributes_destroy(
102     xsd_anyAttributes_t                 attrs)
103 44065 {
104 44065     if(attrs)
105     {
106 33331         globus_hashtable_destroy_all(&attrs, xsd_anyAttributes_element_delete);
107     }
108 }
109
110 globus_result_t
111 xsd_anyAttributes_init(
112     xsd_anyAttributes_t *               attrs)
113 22099 {
114 22099     return globus_hashtable_init(attrs, 10, xsd_QName_hash, xsd_QName_keyeq);
115 }
116
117 static
118 int
119 xsd_QName_compare(
120     void *                              a,
121     void *                              b,
122     void *                              args)
123 0 {
124 0     int                                 res;
125 0     xsd_QName *                         qa;
126 0     xsd_QName *                         qb;
127
128     
129 0     if(!a)
130     {
131 0         return 1;
132     }
133
134 0     if(!b)
135     {
136 0         return 0;
137     }
138
139 0     qa = (xsd_QName *)a;
140 0     qb = (xsd_QName *)b;
141
142 0     if(!qa->Namespace && !qb->Namespace)
143     {
144 0         globus_assert_string(qa->local && qb->local, 
145                              "QName structs must have valid local values");
146         
147 0         if(strcmp(qa->local, qb->local) <= 0)
148         {
149 0             return 1;
150         }
151         
152 0         return 0;
153     }
154
155 0     if(qa->Namespace && qb->Namespace)
156     {
157 0         res = strcmp(qa->Namespace, qb->Namespace);
158 0         if(res == 0)
159         {
160 0             if(strcmp(qa->local, qb->local) <= 0)
161             {
162 0                 return 1;
163             }
164
165 0             return 0;
166         }
167         
168 0         if(res < 0)
169         {
170 0             return 1;
171         }
172
173 0         return 0;
174     }
175          
176 0     if((!qa->Namespace) && qb->Namespace)
177     {
178 0         return 1;
179     }
180
181 0     if((!qb->Namespace) && qa->Namespace)
182     {
183 0         return 0;
184     }
185
186 0     return 1;
187 }
188
189 globus_list_t *
190 xsd_anyAttributes_lex_sort(
191     xsd_anyAttributes_t                 attrs)
192 0 {
193 0     xsd_l_anyAttributes_element_t *     element;
194 0     globus_list_t *                     keys = NULL;
195     
196 0     element = (xsd_l_anyAttributes_element_t *) globus_hashtable_first(&attrs);
197 0     while(element)
198     {
199 0         globus_list_insert(&keys, &element->qname);
200 0         element = (xsd_l_anyAttributes_element_t *) 
201             globus_hashtable_next(&attrs);
202     }
203
204 0     keys = globus_list_sort(keys, xsd_QName_compare, NULL);
205
206 0     return keys;
207 }
208
209 globus_result_t
210 xsd_anyAttributes_namespace_set(
211     globus_soap_message_handle_t        message,
212     xsd_anyAttributes_t                 attrs,
213     globus_xsd_element_options_t *      options)
214 21615 {
215 21615     globus_result_t                     result = GLOBUS_SUCCESS;
216 21615     xsd_l_anyAttributes_element_t *     element;
217 21615     if(attrs)
218     {
219 0         element = globus_hashtable_first(&attrs);
220 0         while(element)
221         {
222 0             result = globus_soap_message_attribute_ns_set(
223                 message,
224                 element->qname.Namespace,
225                 options);
226 0             if(result != GLOBUS_SUCCESS)
227             {
228 0                 xsd_QName *             eqn = &element->qname;
229 0                 result = GlobusSoapMessageErrorSerializeFailed(
230                     result, NULL, eqn);
231 0                 goto exit;
232             }
233
234 0             element = globus_hashtable_next(&attrs);
235         }
236     }
237
238 exit:
239     
240 21615     return result;
241 }
242 globus_result_t
243 xsd_anyAttributes_namespace_add(
244     globus_soap_message_handle_t        message,
245     xsd_anyAttributes_t                 attrs,
246     globus_xsd_element_options_t *      options)
247 21615 {
248 21615     globus_result_t                     result = GLOBUS_SUCCESS;
249 21615     xsd_l_anyAttributes_element_t *     element;
250 21615     if(attrs)
251     {
252 0         element = globus_hashtable_first(&attrs);
253 0         while(element)
254         {
255 0             result = globus_soap_message_attribute_ns_add(
256                 message,
257                 element->qname.Namespace,
258                 options);
259 0             if(result != GLOBUS_SUCCESS)
260             {
261 0                 xsd_QName *             eqn = &element->qname;
262 0                 result = GlobusSoapMessageErrorSerializeFailed(
263                     result, NULL, eqn);
264 0                 goto exit;
265             }
266
267 0             element = globus_hashtable_next(&attrs);
268         }
269     }
270
271 exit:
272     
273 21615     return result;
274 }
275
276 globus_result_t
277 xsd_anyAttributes_namespace_remove(
278     globus_soap_message_handle_t        message,
279     xsd_anyAttributes_t                 attrs,
280     globus_xsd_element_options_t *      options)
281 21615 {
282 21615     globus_result_t                     result = GLOBUS_SUCCESS;
283 21615     xsd_l_anyAttributes_element_t *     element;
284 21615     if(attrs)
285     {
286 0         element = globus_hashtable_first(&attrs);
287 0         while(element)
288         {
289 0             globus_soap_message_attribute_ns_remove(
290                 message,
291                 element->qname.Namespace,
292                 options);
293 0             if(result != GLOBUS_SUCCESS)
294             {
295 0                 xsd_QName *             eqn = &element->qname;
296 0                 result = GlobusSoapMessageErrorSerializeFailed(
297                     result, NULL, eqn);
298 0                 goto exit;
299             }
300
301 0             element = globus_hashtable_next(&attrs);
302         }
303     }
304
305 exit:
306     
307 21615     return result;
308 }
309
310 globus_result_t
311 xsd_anyAttributes_serialize(
312     globus_soap_message_handle_t        message,
313     xsd_anyAttributes_t                 attrs)
314 0 {
315 0     globus_list_t *                     lex_sorted_keys;
316 0     globus_result_t                     result = GLOBUS_SUCCESS;
317 0     xsd_l_anyAttributes_element_t *     element;
318 0     xsd_QName *                         key;
319
320 0     lex_sorted_keys = xsd_anyAttributes_lex_sort(attrs);
321
322 0     key = globus_list_first(lex_sorted_keys);
323 0     while(key)
324     {
325 0         lex_sorted_keys = globus_list_rest(lex_sorted_keys);
326 0         element = (xsd_l_anyAttributes_element_t *) 
327             globus_hashtable_lookup(&attrs, key);
328 0         if(!element)
329         {
330 0             result = GlobusSoapMessageErrorSerializeAnyAttrsFailed(
331                 result, "Null element in attributes list");
332 0             goto exit;
333         }
334         
335 0         result = xsd_string_serialize_attribute(
336             &element->qname, &element->value, message, 0);
337 0         if(result != GLOBUS_SUCCESS)
338         {
339 0             result = GlobusSoapMessageErrorSerializeAnyAttrsFailed(
340                 result, "Failed to serialize any attribute");
341 0             goto exit;
342         }
343      
344 0         key = globus_list_first(lex_sorted_keys);
345     }
346
347  exit:
348
349 0     return result;
350 }
351
352 globus_result_t
353 xsd_anyAttributes_serialize_lex_before(
354     globus_soap_message_handle_t        message,
355     globus_list_t **                    lex_sorted_keys,
356     xsd_anyAttributes_t                 attrs,
357     xsd_QName *                         comparable_value)
358 0 {
359 0     globus_result_t                     result = GLOBUS_SUCCESS;
360 0     xsd_l_anyAttributes_element_t *     element;
361 0     xsd_QName *                         key;
362
363 0     while(*lex_sorted_keys)
364     {
365 0         key = globus_list_first(*lex_sorted_keys);
366         
367 0         if(!xsd_QName_compare(comparable_value, key, NULL))
368         {
369 0     break;
370         } 
371          
372 0         element = (xsd_l_anyAttributes_element_t *) 
373             globus_hashtable_lookup(&attrs, key);
374 0         if(!element)
375         {
376 0             result = GlobusSoapMessageErrorSerializeAnyAttrsFailed(
377                 result, "Null element in attributes list");
378 0             goto exit;
379         }
380         
381 0         result = xsd_string_serialize_attribute(
382             &element->qname, &element->value, message, 0);
383 0         if(result != GLOBUS_SUCCESS)
384         {
385 0             result = GlobusSoapMessageErrorSerializeAnyAttrsFailed(
386                 result, "Failed to serialize any attribute");
387 0             goto exit;
388         }
389      
390 0         *lex_sorted_keys = globus_list_rest(*lex_sorted_keys);
391     }
392
393  exit:
394
395 0     return result;
396 }
397
398 static
399 void
400 xsd_anyAttributes_QName_copy_callback(
401     void **                             dest_key,
402     void **                             dest_datum,
403     void *                              src_key,
404     void *                              src_datum)
405 475 {
406 475     xsd_l_anyAttributes_element_t *     dest_element;
407 475     xsd_l_anyAttributes_element_t *     src_element;
408
409 475     src_element = (xsd_l_anyAttributes_element_t *) src_datum;
410
411 475     dest_element = (xsd_l_anyAttributes_element_t *)
412         globus_malloc(sizeof(xsd_l_anyAttributes_element_t));
413
414 475     xsd_QName_copy_contents(&dest_element->qname, (const xsd_QName *) src_key);
415 475     dest_element->value = globus_libc_strdup(src_element->value);
416
417 475     *dest_datum = dest_element;
418 475     *dest_key = &dest_element->qname;
419 }
420
421 globus_result_t
422 xsd_anyAttributes_copy(
423     xsd_anyAttributes_t *               dest_attrs,
424     xsd_anyAttributes_t                 src_attrs)
425 11232 {
426 11232     globus_result_t                     result = GLOBUS_SUCCESS;
427
428 11232     result = globus_hashtable_copy(dest_attrs, &src_attrs, 
429                                    xsd_anyAttributes_QName_copy_callback);
430     
431 11232     return result;
432 }
433
434 globus_result_t
435 xsd_anyAttributes_deserialize(
436     globus_soap_message_handle_t        message,
437     xsd_anyAttributes_t                 attrs)
438 22099 {
439 22099     globus_result_t                     result = GLOBUS_SUCCESS;
440 22099     int                                 res = 0;
441
442 22099     res = xmlTextReaderMoveToFirstAttribute(message->reader);
443 22099     if(res < 0)
444     {
445 0         result = GlobusSoapMessageErrorDeserializeAnyAttrsFailed(
446             message->result, NULL);
447
448 0         goto exit;
449     }
450
451 42466     while(res)
452     {
453 20367         xmlNodePtr                      attrNode;
454 20367         xsd_l_anyAttributes_element_t * element;
455         
456 20367         attrNode = xmlTextReaderCurrentNode(message->reader);
457 20367         if(attrNode->type == XML_ATTRIBUTE_NODE)
458         {
459 2849             element = (xsd_l_anyAttributes_element_t *)
460                 globus_malloc(sizeof(xsd_l_anyAttributes_element_t));
461 2849             element->qname.local = xmlTextReaderLocalName(message->reader);
462 2849             element->qname.Namespace =
463                 xmlTextReaderNamespaceUri(message->reader);
464 2849             element->value = xmlTextReaderValue(message->reader);
465             
466 2849             globus_hashtable_insert(&attrs, &element->qname, element);
467         }
468
469 20367         res = xmlTextReaderMoveToNextAttribute(message->reader);
470 20367         if(res == -1)
471         {
472 0             result = GlobusSoapMessageErrorDeserializeAnyAttrsFailed(
473                 message->result, NULL);
474 0             goto exit;
475         }
476     }
477
478 22099     res = xmlTextReaderMoveToElement(message->reader);
479 22099     if(res < 0)
480     {
481 0         result = GlobusSoapMessageErrorDeserializeAnyAttrsFailed(
482             message->result, NULL);
483
484         goto exit;
485     }
486
487  exit:
488
489 22099     return result;