> I think we don't need to care whether it is abstract or not. The > polymorphism can occur for any complex type. (that any where complex > content extension goes). So we should not assume it happens only to > abstract types.
I completely agree, I won't assume that at all. I'll also have to make sure this works with multiple levels of inheritance. I was just trying to make a strong case of why this is needed ;-) Regarding your suggestions, Carl, Dimuthu, thanks for the help. I've been thinking about this quite a bit, and I think I have an approach too. Like it was suggested, I was thinking of making two global "flat" functions (either in the stubs or in a separate file, that's just a matter of preference) that would be used for all serialization and deserialization. Now, here's where it differs: each type would retain its own serialization and deserialization functions exactly as they are, but change the name to something like *_serialize_impl and *_deserialize_impl. Also, for compatibility purposes, and to reduce the amount of changes needed, they would also have *_serialize and *_deserialize functions, but they would just be wrappers that would call the "global" functions. Now, these "global" functions would know all the types, and would be able to call the appropriate *_impl functions for them. For serialization to work, we need to store the type name in every structure, per Carl's suggestion. For deserialization to work, we would need to check the type name (xsi:Type) in the node. So, in terms of code, this would be, as suggested: struct adbType { axis2_char_t property_Type[64]; } and of course, for other types, e.g. A1: struct adb_A1 { axis2_char_t property_Type[64]; ... } So, the global serialization function could be: axiom_node_t* AXIS2_CALL adb_serialize( adbType_t* _element, const axutil_env_t *env, axiom_node_t *parent, axiom_element_t *parent_element, int parent_tag_closed, axutil_hash_t *namespaces, int *next_ns_index) { if (strcmp(struct->property_Type, "adb_A") == 0) { return adb_A_serialize_impl((adb_A_t *)_element, env, parent, parent_element, parent_tag_closed, namespaces, next_ns_index); } if (strcmp(struct->property_Type, "adb_A1") == 0) { return adb_A1_serialize_impl((adb_A1_t *)_element, env, parent, parent_element, parent_tag_closed, namespaces, next_ns_index); } ... } Note that A is also listed as a type, even though it's abstract. Admittedly, not an ideal solution, but necessary to make sure that you could instance a pure A object if it weren't abstract. The global deserialization function: axis2_status_t AXIS2_CALL adb_deserialize( adbType_t* _element, const axutil_env_t *env, axiom_node_t **dp_parent, axis2_bool_t *dp_is_early_node_valid, axis2_bool_t dont_care_minoccurs) { if (/* is xsi:Type == "A" ? */) { return adb_A_deserialize_impl((adb_A_t *)_element, env, dp_parent, dp_is_early_node_valid, dont_care_minoccurs); } if (/* is xsi:Type == "A1" ? */) { return adb_A1_deserialize_impl((adb_A1_t *)_element, env, dp_parent, dp_is_early_node_valid, dont_care_minoccurs); } ... } The wrapper functions would simply look like this: axiom_node_t* AXIS2_CALL adb_A_serialize( adb_A_t* _A, const axutil_env_t *env, axiom_node_t *parent, axiom_element_t *parent_element, int parent_tag_closed, axutil_hash_t *namespaces, int *next_ns_index) { return adb_serialize((adbType_t *)_A, env, parent, parent_element, parent_tag_closed, namespaces, next_ns_index); } axis2_status_t AXIS2_CALL adb_deserialize( adb_A_t* _A, const axutil_env_t *env, axiom_node_t **dp_parent, axis2_bool_t *dp_is_early_node_valid, axis2_bool_t dont_care_minoccurs) { return adb_deserialize((adbType_t *)_A, env, dp_parent, dp_is_early_node_valid, dont_care_minoccurs); } This approach is very similar to what Dimuthu suggested, but it would have the benefit of "plugging into" the existing infrastructure, and would require no changes to the complex code inside the serialization/deserialization functions. Probably not as elegant, though. Overall, I think Dimuthu's suggestion is better, but scarier ;-) I'm just putting mine forward to get your opinions. Neither of these would assure that you could only instance objects of the specific type hierarchy you're expecting, however. Where would this get done, and does it matter if it isn't? Cheers, Sérgio --- On Fri, May 30, 2008 at 5:17 AM, Dimuthu Gamage <[EMAIL PROTECTED]> wrote: > On Thu, May 29, 2008 at 8:02 PM, Lefrancois, Carl > <[EMAIL PROTECTED]> wrote: >>>>I'm developing a patch against the ADB C code generator to allow it to >> handle polymorphism correctly... >> >>>>Say you have a complexType A, which is abstract. Then there are >> complexTypes A1 and A2, which extend A and are not abstract. >> >>>>The second case, however, is quite problematic. The only way to know >> which type is being returned is, of course, during runtime, by looking >> at the xsi:type property. This is relatively easy to do with Axiom, but >> the problem is how to invoke the right create method, but the problem is >> that for this to work correctly, it's necessary to invoke the "create" >> and "deserialize" methods for the right subtype (the ones for A won't >> do, as they aren't aware of the specific properties of A1 and A2). I >> thought of creating one global hash table with the create/deserialize >> methods for all types when generating the stub for the service, but it >> doesn't strike me as a particularly elegant solution. Does anyone have >> any other suggestions? >> >>>>It's at times like these I wish C had classes and I could just let the >> language handle the issue itself ;-) >> >>>>Cheers, >>>>Sérgio >> >> >> >> Hi Sérgio, >> >> As Dimuthu suggested in an earlier post, you can change the structure of >> each subtype to start with a char array, then casting the object to a >> char * will give you the contents of this char array. >> >> E.g. The source file for type A1 will contain >> >> struct adb_A1 >> { >> ... >> } >> >> If we change this to: >> struct adb_A1 >> { >> axis2_char_t property_Type[64]; >> ... >> } >> >> And in the adb_A1_create, add >> strcpy(_A1->property_Type, "adb_A1"); >> >> >> In the same way, adb_A2.c contains >> >> struct adb_A2 >> { >> axis2_char_t property_Type[64]; >> ... >> } >> >> in adb_A2_create >> strcpy(_A2->property_Type, "adb_A2"); >> >> >> So now consider an ADB object C that contains an element of base type A. >> in adb_C.c you will have >> >> >> adb_C_set_A(C_t *C, env, A_t *A) >> { >> ... >> } >> >> Change this to >> adb_C_set_A(C_t *C, env, void *A) >> >> The void * will be correctly stored in the property or array list. >> >> During serialization, you can use the following: >> >> if (strcmp((char *)element, "adb_A1") == 0) { >> >> if(!adb_A1_is_particle()) >> { >> axutil_stream_write(stream, env, start_input_str, >> start_input_str_len); >> } >> >> adb_A1_serialize((adb_A1_t*)element, >> env, >> current_node, parent_element, >> >> adb_A1_is_particle() || AXIS2_FALSE, namespaces, next_ns_index); >> >> if(!adb_A1_is_particle()) >> { >> axutil_stream_write(stream, env, end_input_str, >> end_input_str_len); >> } >> } >> >> And repeat for A2, etc. >> >> Now the final usage pattern looks like this: >> >> Adb_C = adb_C_create(env); >> Adb_A1 = adb_A1_create(env); >> Adb_C_set_A(Adb_C, env, Adb_A1); >> >> And the C will correctly serialize the element as an A1. >> >> >> I hope this helps your work. I am really interested in seeing this >> implemented in WSDL2C. >> >> Carl > > Hi Carl, > > Here 'A' have to aware of the fact A1 and A2 are inheriting from it. > In current codegen implementation it is bit hard to implement. (need > to change the codegen engine implementation). The best thing is let > the mapping to do from external file, (some corresponding file to > 'ExtensionMapper.java'). So I will change your suggested code to > something like this.. > > void adb_A_serialize(void *element, ....) > { > > /* serialize 'A' s element first */ > if(!adb_A_is_particle()) > { > axutil_stream_write(stream, env, start_input_str, > start_input_str_len); > } > > serialize_content_func = > axis2_extension_mapper_get_serialize_content_func(element); > > serialize_content_func(element, > env, > current_node, parent_element, > adb_A1_is_particle() || AXIS2_FALSE, namespaces, next_ns_index); > > > if(!adb_A_is_particle()) > { > axutil_stream_write(stream, env, end_input_str, > end_input_str_len); > } > > } > > And some external file like axis2_extension_mapper.c we have the > mapping function. It returns the correct serialize function for the > element > > /* for example for serialize_content function */ > > typedef void (*ret_func_ptr)(void *element, axutil_env_t *env, ..); > > ret_func_ptr axis2_extension_mapper_get_serialize_content_func(void *element) > { > if(strcmp((axis2_char_t*)(element), "A1")) > { > return adb_A1_serialize_content; > } > if(strcmp((axis2_char_t*)(element), "A2")) > { > return adb_A2_serialize_content; > } > } > > > Thanks > Dimuthu > >> _____ >> >> "Ce message est confidentiel, à l'usage exclusif du destinataire >> ci-dessus et son contenu ne représente en aucun cas un engagement de la >> part de AXA, sauf en cas de stipulation expresse et par écrit de la part >> de AXA. Toute publication, utilisation ou diffusion, même partielle, >> doit être autorisée préalablement. Si vous n'êtes pas destinataire de ce >> message, merci d'en avertir immédiatement l'expéditeur." >> >> "This e-mail message is confidential, for the exclusive use of the >> addressee and its contents shall not constitute a commitment by AXA, >> except as otherwise specifically provided in writing by AXA. Any >> unauthorized disclosure, use or dissemination, either whole or partial, >> is prohibited. If you are not the intended recipient of the message, >> please notify the sender immediately." >> >> --------------------------------------------------------------------- >> To unsubscribe, e-mail: [EMAIL PROTECTED] >> For additional commands, e-mail: [EMAIL PROTECTED] >> >> > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > > --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]