diff options
Diffstat (limited to 'modules/CIAO/tools/IDL3_to_XMI/IDL3_to_XMI_visitor.cpp')
-rw-r--r-- | modules/CIAO/tools/IDL3_to_XMI/IDL3_to_XMI_visitor.cpp | 2573 |
1 files changed, 2573 insertions, 0 deletions
diff --git a/modules/CIAO/tools/IDL3_to_XMI/IDL3_to_XMI_visitor.cpp b/modules/CIAO/tools/IDL3_to_XMI/IDL3_to_XMI_visitor.cpp new file mode 100644 index 00000000000..06758c47d1b --- /dev/null +++ b/modules/CIAO/tools/IDL3_to_XMI/IDL3_to_XMI_visitor.cpp @@ -0,0 +1,2573 @@ +// $Id$ + +#include "IDL3_to_XMI_visitor.h" +#include "identifier_helper.h" + +#include "be_sunsoft.h" +#include "be_extern.h" + +#include "ast_argument.h" +#include "ast_array.h" +#include "ast_attribute.h" +#include "ast_component_fwd.h" +#include "ast_enum.h" +#include "ast_enum_val.h" +#include "ast_eventtype.h" +#include "ast_eventtype_fwd.h" +#include "ast_exception.h" +#include "ast_factory.h" +#include "ast_field.h" +#include "ast_home.h" +#include "ast_operation.h" +#include "ast_root.h" +#include "ast_sequence.h" +#include "ast_string.h" +#include "ast_structure_fwd.h" +#include "ast_union.h" +#include "ast_union_branch.h" +#include "ast_union_fwd.h" +#include "ast_union_label.h" +#include "ast_valuebox.h" +#include "ast_valuetype_fwd.h" +#include "ast_native.h" +#include "utl_exceptlist.h" +#include "utl_identifier.h" +#include "utl_idlist.h" +#include "utl_string.h" +#include "global_extern.h" +#include "nr_extern.h" +#include "ace/OS_NS_stdio.h" +#include "ace/OS_NS_sys_time.h" +#include "ace/ACE.h" + +#include "Literals.h" +#include "XML/XercesString.h" + +#include <iostream> +#include <limits> +#include <sstream> + +#include "xercesc/dom/DOM.hpp" +#include "xercesc/util/XMLChar.hpp" + +#include "XML/XML_Helper.h" + +using XERCES_CPP_NAMESPACE::DOMDocument; +using XERCES_CPP_NAMESPACE::DOMAttr; +using XERCES_CPP_NAMESPACE::DOMElement; +using XERCES_CPP_NAMESPACE::DOMText; +using XERCES_CPP_NAMESPACE::DOMDocumentType; +using XERCES_CPP_NAMESPACE::XMLChar1_1; +using CIAO::XML::XStr; + + + +#if 0 +struct Foo { + std::string foo_; + Foo (const char *foo) : foo_ (foo) + { + std::cout << "Entering " << foo_ << std::endl; + } + ~Foo () + { + std::cout << "Leaving " << foo_ << std::endl; + } +}; + +#define XMI_TRACE(X) Foo _foobarbaz (X); +#else +#define XMI_TRACE(X) +#endif + +namespace CIAO +{ + namespace XMI + { + size_t idl3_to_xmi_visitor::current_id_ = 0; + + template <typename T> + ACE_TCHAR * + idl3_to_xmi_visitor::number_to_string (T val) + { + std::stringstream str; + + str << val; + + return ACE::strnew (ACE_TEXT_CHAR_TO_TCHAR (str.str ().c_str ())); + } + + template <> + ACE_TCHAR * + idl3_to_xmi_visitor::number_to_string (bool val) + { + if (val) + return ACE::strnew (LITERALS[CAPS_TRUE]); + else + return ACE::strnew (LITERALS[CAPS_FALSE]); + } + + template <> + ACE_TCHAR * + idl3_to_xmi_visitor::number_to_string (char val) + { + // There is no way to convert any char to xml encoding nicely + // so we convert it to a decimal integer. This will preserve at + // least a correct char value instead of some non-printable xml. + std::stringstream str; + + str << static_cast<unsigned int>(static_cast<unsigned char> (val)); + + return ACE::strnew (ACE_TEXT_CHAR_TO_TCHAR (str.str ().c_str ())); + } + + template <> + ACE_TCHAR * + idl3_to_xmi_visitor::number_to_string (wchar_t val) + { + // There is no way to convert any char to xml encoding nicely + // so we convert it to a decimal integer. This will preserve at + // least a correct char value instead of some non-printable xml. + std::stringstream str; + + str << static_cast<unsigned long>(static_cast<wchar_t> (val)); + + return ACE::strnew (ACE_TEXT_CHAR_TO_TCHAR (str.str ().c_str ())); + } + + idl3_to_xmi_visitor::idl3_to_xmi_visitor (bool skip_imported) + : dom_ (0), + root_ (0), + generalizations_ (0), + associations_ (0), + base_id_ (idl3_to_xmi_visitor::gen_xmi_id ()), + skip_imported_ (skip_imported), + visiting_enum_ (false), + union_disc_ (0) + { + } + + idl3_to_xmi_visitor::~idl3_to_xmi_visitor (void) + { + } + + int + idl3_to_xmi_visitor::visit_decl (AST_Decl *) + { + XMI_TRACE ("got a decl"); + return 0; + } + + char * + copy_scoped_name (UTL_ScopedName *name) + { + ACE_CString fullname; + for (UTL_ScopedNameActiveIterator si (name); + !si.is_done (); + si.next ()) + { + Identifier *item = si.item (); + fullname += item->get_string (); + } + + return fullname.rep (); + } + + int + idl3_to_xmi_visitor::visit_scope (UTL_Scope *node) + { + XMI_TRACE ("got a scope"); + + this->order_ = 0; + + for (UTL_ScopeActiveIterator si (node, UTL_Scope::IK_decls); + !si.is_done (); + si.next ()) + { + AST_Decl *d = si.item (); + d->ast_accept (this); + ++this->order_; + } + return 0; + } + + int + idl3_to_xmi_visitor::visit_type (AST_Type *) + { + XMI_TRACE ("got a type"); + return 0; + } + + int + idl3_to_xmi_visitor::visit_predefined_type (AST_PredefinedType *node) + { + XMI_TRACE ("predef type"); + + char const *local_name = 0; + switch (node->pt ()) + { + case AST_PredefinedType::PT_pseudo: + // Only a limited number of predefined pseudo types + // needs our attention. + local_name = node->original_local_name ()->get_string (); + if (ACE_OS::strcmp (local_name, "TypeCode") == 0) + { + ES_Guard class_guard (LITERALS[CLASS_TAG], this); + this->gen_common_elements (node, LITERALS[ST_TC]); + } + default: + break; + } + return 0; + } + + int + idl3_to_xmi_visitor::visit_module (AST_Module *node) + { + XMI_TRACE ("module"); + + try + { + DOMElement * ele = 0; + if (this->repo_id_map_.find (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele) == 0) + { + // If the module is reopened then put it on the stack. + ES_Guard (ele, this); + this->visit_scope (node); + // And don't do anything more. + return 0; + } + + ES_Guard package_guard (LITERALS[PACKAGE_TAG], this); + + this->gen_common_elements (node, LITERALS[ST_MODULE]); + + { + NS_Guard ns_guard ((ACE_TEXT_CHAR_TO_TCHAR (node->repoID ())), this); + ES_Guard owned_guard (LITERALS[OWNEDELEMENT_TAG], this); + + // Save ownedElement to add to it later if the module + // will be reopened. + DOMElement *ele = 0; + this->stack_.top (ele); + this->repo_id_map_.bind (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele); + + this->visit_scope (node); + } + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + int + idl3_to_xmi_visitor::visit_interface (AST_Interface *node) + { + XMI_TRACE ("interface"); + + if (this->skip_imported_ && node->imported ()) + { + this->visit_scope (node); + return 0; + } + + try + { + DOMElement * ele = 0; + if (this->repo_id_map_.find (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele) != 0) + { + ES_Guard class_guard (LITERALS[CLASS_TAG], this); + + this->gen_common_elements (node, LITERALS[ST_INTF]); + + // Save in order not to generate same element later. + this->stack_.top (ele); + this->repo_id_map_.bind (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele); + } + + ES_Guard class_guard (ele, this); + NS_Guard ns_guard (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), this); + + { // Operations. + ES_Guard owned_guard (LITERALS[OWNEDELEMENT_TAG], this); + this->cached_type_ = node; + this->visit_scope (node); + this->cached_type_ = 0; + } + + // Inheritance + for (long i = 0; i < node->n_inherits (); ++i) + { + XStr xid (this->add_generalization ( + ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), + ACE_TEXT_CHAR_TO_TCHAR (node->inherits ()[i]->repoID ()))); + } + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + int + idl3_to_xmi_visitor::visit_interface_fwd (AST_InterfaceFwd *node) + { + XMI_TRACE ("interface_fwd"); + + try + { + DOMElement * ele = 0; + if (this->repo_id_map_.find (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele) != 0) + { + ES_Guard class_guard (LITERALS[CLASS_TAG], this); + + this->gen_common_elements (node, LITERALS[ST_INTF]); + + // Save in order not to generate same element later. + this->stack_.top (ele); + this->repo_id_map_.bind (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele); + } + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + int + idl3_to_xmi_visitor::visit_valuebox (AST_ValueBox *node) + { + XMI_TRACE ("valuebox"); + + if (this->skip_imported_ && node->imported ()) + { + return 0; + } + + try + { + ES_Guard class_guard (LITERALS[CLASS_TAG], this); + this->gen_common_elements (node, LITERALS[ST_BOXVALUE]); + + // add a generalization for the value we box + XStr xid (this->add_generalization ( + ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), + ACE_TEXT_CHAR_TO_TCHAR (node->boxed_type ()->repoID ()))); + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + int + idl3_to_xmi_visitor::visit_valuetype (AST_ValueType *node) + { + XMI_TRACE ("valuetype"); + + if (this->skip_imported_ && node->imported ()) + { + this->visit_scope (node); + return 0; + } + + try + { + DOMElement * ele = 0; + if (this->repo_id_map_.find (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele) != 0) + { + ES_Guard class_guard (LITERALS[CLASS_TAG], this); + + this->gen_common_elements (node, LITERALS[ST_VALUE]); + + // Save in order not to generate same element later. + this->stack_.top (ele); + this->repo_id_map_.bind (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele); + } + + ES_Guard class_guard (ele, this); + + this->visit_valuetype_impl (node); + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + void + idl3_to_xmi_visitor::visit_valuetype_impl (AST_ValueType *node) + { + try + { + // isAbstract + if (node->is_abstract ()) + { + this->set_attribute (LITERALS[ABSTRACT], LITERALS[_TRUE]); + } + else + { + this->set_attribute (LITERALS[ABSTRACT], LITERALS[_FALSE]); + } + + NS_Guard ns_guard (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), this); + + if (node->inherits_concrete () != 0) + { + XStr xid (this->add_generalization ( + ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), + ACE_TEXT_CHAR_TO_TCHAR (node->inherits_concrete ()->repoID ()))); + } + + for (long i = 0; i < node->n_supports (); ++i) + { + XStr xid (this->add_generalization ( + ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), + ACE_TEXT_CHAR_TO_TCHAR (node->supports ()[i]->repoID ()))); + } + + /* NOTE: CDMW XMI generator ignores supports specifications. + // Supports + if (node->n_supports () != 0) + throw Error ("ValueTypes which support are not currently supported.", node); + */ + + ES_Guard oe_guard (LITERALS[OWNEDELEMENT_TAG], this); + + this->cached_type_ = node; + this->visit_scope (node); + this->cached_type_ = 0; + } + catch (Error &err) + { + err.node (node); + throw; + } + } + + int + idl3_to_xmi_visitor::visit_valuetype_fwd (AST_ValueTypeFwd *node) + { + XMI_TRACE ("valuetype_fwd"); + + try + { + DOMElement * ele = 0; + if (this->repo_id_map_.find (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele) != 0) + { + ES_Guard class_guard (LITERALS[CLASS_TAG], this); + + this->gen_common_elements (node, LITERALS[ST_VALUE]); + + // Save in order not to generate same element later. + this->stack_.top (ele); + this->repo_id_map_.bind (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele); + } + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + int + idl3_to_xmi_visitor::visit_component (AST_Component *node) + { + XMI_TRACE ("component"); + + if (this->skip_imported_ && node->imported ()) + { + this->visit_scope (node); + return 0; + } + + try + { + DOMElement * ele = 0; + if (this->repo_id_map_.find (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele) != 0) + { + ES_Guard class_guard (LITERALS[CLASS_TAG], this); + + this->gen_common_elements (node, LITERALS[ST_COMP]); + + // Save in order not to generate same element later. + this->stack_.top (ele); + this->repo_id_map_.bind (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele); + } + + ES_Guard class_guard (ele, this); + NS_Guard ns_guard (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), this); + + for (long i = 0; i < node->n_supports (); ++i) + { + XStr xid (this->add_generalization ( + ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), + ACE_TEXT_CHAR_TO_TCHAR (node->supports ()[i]->repoID ()))); + + } + + if (node->base_component () != 0) + { + XStr xid (this->add_generalization ( + ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), + ACE_TEXT_CHAR_TO_TCHAR (node->base_component ()->repoID ()))); + } + + // Component ports + this->gen_component_ports ( + node->provides (), + ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), + LITERALS[ST_PROVIDES], + ACE_TEXT_CHAR_TO_TCHAR (node->file_name ().c_str ())); + + this->gen_component_ports ( + node->uses (), + ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), + LITERALS[ST_USES], + ACE_TEXT_CHAR_TO_TCHAR (node->file_name ().c_str ())); + + this->gen_component_ports ( + node->emits (), + ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), + LITERALS[ST_EMITS], + ACE_TEXT_CHAR_TO_TCHAR (node->file_name ().c_str ())); + + this->gen_component_ports ( + node->publishes (), + ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), + LITERALS[ST_PUBLISH], + ACE_TEXT_CHAR_TO_TCHAR (node->file_name ().c_str ())); + + this->gen_component_ports ( + node->consumes (), + ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), + LITERALS[ST_CONSUMES], + ACE_TEXT_CHAR_TO_TCHAR (node->file_name ().c_str ())); + + ES_Guard oe_guard (LITERALS[OWNEDELEMENT_TAG], this); + + // attributes in scope. + this->cached_type_ = node; + this->visit_scope (node); + this->cached_type_ = 0; + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + int + idl3_to_xmi_visitor::visit_component_fwd (AST_ComponentFwd *node) + { + XMI_TRACE ("component_fwd"); + + try + { + DOMElement * ele = 0; + if (this->repo_id_map_.find (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele) != 0) + { + ES_Guard class_guard (LITERALS[CLASS_TAG], this); + + this->gen_common_elements (node, LITERALS[ST_COMP]); + + // Save in order not to generate same element later. + this->stack_.top (ele); + this->repo_id_map_.bind (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele); + } + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + int + idl3_to_xmi_visitor::visit_eventtype (AST_EventType *node) + { + XMI_TRACE ("eventtype"); + + if (this->skip_imported_ && node->imported ()) + { + this->visit_scope (node); + return 0; + } + + try + { + DOMElement * ele = 0; + if (this->repo_id_map_.find (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele) != 0) + { + ES_Guard class_guard (LITERALS[CLASS_TAG], this); + + this->gen_common_elements (node, LITERALS[ST_EVENT]); + + // Save in order not to generate same element later. + this->stack_.top (ele); + this->repo_id_map_.bind (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele); + } + + ES_Guard class_guard (ele, this); + + this->visit_valuetype_impl (node); + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + int + idl3_to_xmi_visitor::visit_eventtype_fwd (AST_EventTypeFwd *node) + { + XMI_TRACE ("eventtype_fwd"); + + this->visit_valuetype_fwd (node); + + return 0; + } + + int + idl3_to_xmi_visitor::visit_home (AST_Home *node) + { + XMI_TRACE ("home"); + + if (this->skip_imported_ && node->imported ()) + { + this->visit_scope (node); + return 0; + } + + try + { + ES_Guard es_guard (LITERALS[CLASS_TAG], this); + + this->gen_common_elements (node, LITERALS[ST_HOME]); + + NS_Guard ns_guard (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), this); + + for (long i = 0; i < node->n_supports (); ++i) + { + XStr xid (this->add_generalization ( + ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), + ACE_TEXT_CHAR_TO_TCHAR (node->supports ()[i]->repoID ()))); + } + + if (node->base_home () != 0) + { + XStr xid (this->add_generalization ( + ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), + ACE_TEXT_CHAR_TO_TCHAR (node->base_home ()->repoID ()))); + } + + if (node->factories ().size () != 0) + { + ES_Guard noe_guard (LITERALS[OWNEDELEMENT_TAG], this); + for (size_t i = 0; i < node->factories ().size (); ++i) + { + AST_Operation **op = 0; + node->factories ().get (op, i); + this->visit_operation_impl (*op, LITERALS[ST_HFACT]); + } + } + + if (node->finders () .size () != 0) + throw Error ("home finders not supported", node); + + this->add_managed_component ( + ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), + ACE_TEXT_CHAR_TO_TCHAR (node->managed_component ()->repoID ())); + + ES_Guard noe_guard (LITERALS[OWNEDELEMENT_TAG], this); + + // attributes in scope. + this->cached_type_ = node; + this->visit_scope (node); + this->cached_type_ = 0; + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + int + idl3_to_xmi_visitor::visit_factory (AST_Factory *node) + { + XMI_TRACE ("factory"); + + if (this->skip_imported_ && node->imported ()) + { + return 0; + } + + throw Error ("Factories not supported", node); + + return 0; + } + + int + idl3_to_xmi_visitor::visit_structure (AST_Structure *node) + { + XMI_TRACE ("structure"); + + if (this->skip_imported_ && node->imported ()) + { + this->visit_scope (node); + return 0; + } + + try + { + DOMElement * ele = 0; + if (this->repo_id_map_.find (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele) != 0) + { + ES_Guard class_guard (LITERALS[CLASS_TAG], this); + + this->gen_common_elements (node, LITERALS[ST_STRUCT]); + + // Save in order not to generate same element later. + this->stack_.top (ele); + this->repo_id_map_.bind (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele); + } + + ES_Guard class_guard (ele, this); + + this->visit_struct_impl (node); + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + void + idl3_to_xmi_visitor::visit_struct_impl (AST_Structure *node) + { + try + { + ES_Guard ns_oe_guard (LITERALS[OWNEDELEMENT_TAG], this); + NS_Guard ns_guard (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), this); + this->visit_scope (node); + } + catch (Error &err) + { + err.node (node); + throw; + } + } + + int + idl3_to_xmi_visitor::visit_structure_fwd (AST_StructureFwd *node) + { + XMI_TRACE ("structure_fwd"); + + try + { + DOMElement * ele = 0; + if (this->repo_id_map_.find (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele) != 0) + { + ES_Guard class_guard (LITERALS[CLASS_TAG], this); + + this->gen_common_elements (node, LITERALS[ST_STRUCT]); + + // Save in order not to generate same element later. + this->stack_.top (ele); + this->repo_id_map_.bind (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele); + } + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + int + idl3_to_xmi_visitor::visit_exception (AST_Exception *node) + { + XMI_TRACE ("exception"); + + if (this->skip_imported_ && node->imported ()) + { + this->visit_scope (node); + return 0; + } + + try + { + DOMElement * ele = 0; + if (this->repo_id_map_.find (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele) != 0) + { + ES_Guard class_guard (LITERALS[EXCEPTION_TAG], this); + + this->gen_common_elements (node, LITERALS[ST_EX]); + + // Save in order not to generate same element later. + this->stack_.top (ele); + this->repo_id_map_.bind (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele); + } + + ES_Guard class_guard (ele, this); + + this->visit_struct_impl (node); + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + int + idl3_to_xmi_visitor::visit_expression (AST_Expression *) + { + XMI_TRACE ("expression"); + + // we don't particularly care about expressions. + + return 0; + } + + int + idl3_to_xmi_visitor::visit_enum (AST_Enum *node) + { + XMI_TRACE ("enum"); + + if (this->skip_imported_ && node->imported ()) + { + this->visit_scope (node); + return 0; + } + + try + { + ES_Guard es_guard (LITERALS[CLASS_TAG], this); + this->gen_common_elements (node, LITERALS[ST_ENUM]); + + NS_Guard ns_guard (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), this); + ES_Guard oe_guard (LITERALS[OWNEDELEMENT_TAG], this); + + this->visiting_enum_ = true; + this->visit_scope (node); + this->visiting_enum_ = false; + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + void + idl3_to_xmi_visitor::visit_operation_impl (AST_Operation *op, + const ACE_TCHAR *stereotype) + { + XMI_TRACE ("operation"); + + if (this->skip_imported_ && op->imported ()) + { + this->visit_scope (op); + return; + } + + // This is a mess because the operation has so many special cases.... + try + { + ES_Guard op_guard (LITERALS[OP_TAG], this); + + // name and visiblity + this->set_attribute ( + LITERALS[NAME], + ACE_TEXT_CHAR_TO_TCHAR (op->original_local_name ()->get_string ())); + + this->set_attribute (LITERALS[VISIBIL], LITERALS[PUBLIC]); + + this->set_containing_element (LITERALS[OWNER]); + + // If we have a stereotype, set it + if (stereotype != 0) + this->find_and_set_xid_as_attr (LITERALS[STEREO_ATTR], + stereotype); + + // XMI ID + this->create_and_store_xmi_id (op); + + // while not strictly a namespace, the repo id goes on the + // namespace stack as the owner of contained elements. + NS_Guard ns_guard (ACE_TEXT_CHAR_TO_TCHAR (op->repoID ()), this); + + { // we need to generate the tagged value in a custom way here + ES_Guard me_guard (LITERALS[ME_TV_TAG], this); + + { + ES_Guard tv_guard (LITERALS[TV_TAG], this); + this->set_attribute (LITERALS[TAG], LITERALS[TYPEID]); + this->set_attribute (LITERALS[VALUE], + ACE_TEXT_CHAR_TO_TCHAR (op->repoID ())); + } + + UTL_ExceptList *exceptions = op->exceptions (); + if (exceptions != 0 && exceptions->length () > 0) + { + for (UTL_ExceptlistActiveIterator ei (exceptions); + !ei.is_done (); + ei.next ()) + { + ES_Guard tv_guard (LITERALS[TV_TAG], this); + this->set_attribute (LITERALS[TAG], LITERALS[RAISES]); + this->set_attribute ( + LITERALS[VALUE], + ACE_TEXT_CHAR_TO_TCHAR (ei.item ()->full_name ())); + } + } + } + + ES_Guard bfp_guard (LITERALS[BFP_TAG], this); + + // return value + { + ES_Guard param_guard (LITERALS[PARAM_TAG], this); + + // I don't think anything else can refer to the parameter by + // xid, so I won't store it. + XStr xid = this->gen_xmi_id (op); + + this->set_attribute (LITERALS[XMI_ID], xid); + + this->set_attribute (LITERALS[KIND], LITERALS[RETURN]); + + this->set_containing_element (LITERALS[BFEATURE]); + + xid = this->lookup_type_xid (op->return_type ()); + this->set_attribute (LITERALS[TYPE], + xid); + } + + if (op->argument_count () != 0) + { + // Visit arguments + for (UTL_ScopeActiveIterator si (op, UTL_Scope::IK_decls); + !si.is_done ();) + { + si.item ()->ast_accept (this); + si.next (); + } + } + } + catch (Error &err) + { + err.node (op); + throw; + } + } + + int + idl3_to_xmi_visitor::visit_operation (AST_Operation *op) + { + XMI_TRACE ("operation"); + + this->visit_operation_impl (op, 0); + + return 0; + } + + int + idl3_to_xmi_visitor::visit_field (AST_Field *node) + { + XMI_TRACE ("field"); + + if (this->skip_imported_ && node->imported ()) + { + return 0; + } + + try + { + ES_Guard attr_guard (LITERALS[ATTR_TAG], this); + + if (node->field_type ()->node_type () == AST_Decl::NT_sequence) + { + AST_Sequence* sequence = + AST_Sequence::narrow_from_decl (node->field_type ()); + sequence->ast_accept (this); + // There is no need to proceed any further. + return 0; + } + else if (node->field_type ()->node_type () == AST_Decl::NT_array) + { + AST_Array* array = + AST_Array::narrow_from_decl (node->field_type ()); + array->ast_accept (this); + // There is no need to proceed any further. + return 0; + } + + // I don't think anything else can refer to the parameter by + // xid, so I won't store it. + XStr xid = this->gen_xmi_id (node); + this->set_attribute (LITERALS[XMI_ID], xid); + + this->set_attribute ( + LITERALS[NAME], + ACE_TEXT_CHAR_TO_TCHAR (node->original_local_name ()->get_string ())); + + switch (node->visibility ()) + { + case AST_Field::vis_NA: + case AST_Field::vis_PUBLIC: + this->set_attribute (LITERALS[VISIBIL], LITERALS[PUBLIC]); + break; + case AST_Field::vis_PRIVATE: + this->set_attribute (LITERALS[VISIBIL], LITERALS[_PRIVATE]); + break; + default: + throw Error ("unknown visibility type detected.", node); + } + + // I think this is fixed. + this->set_attribute (LITERALS[MULT], LITERALS[MULT_OTO]); + + this->set_containing_element (LITERALS[OWNER]); + + xid = this->lookup_type_xid (node->field_type ()); + this->set_attribute (LITERALS[TYPE], + xid); + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + int + idl3_to_xmi_visitor::visit_argument (AST_Argument *node) + { + XMI_TRACE ("argument"); + + if (this->skip_imported_ && node->imported ()) + { + return 0; + } + + try + { + ES_Guard param_guard (LITERALS[PARAM_TAG], this); + + this->set_attribute ( + LITERALS[NAME], + ACE_TEXT_CHAR_TO_TCHAR (node->original_local_name ()->get_string ())); + + // I don't think anything else can refer to the parameter by + // xid, so I won't store it. + XStr xid = this->gen_xmi_id (node); + this->set_attribute (LITERALS[XMI_ID], xid); + + // kind + switch (node->direction ()) + { + case AST_Argument::dir_IN: + this->set_attribute (LITERALS[KIND], LITERALS[_IN]); + break; + + case AST_Argument::dir_INOUT: + this->set_attribute (LITERALS[KIND], LITERALS[INOUT]); + break; + + case AST_Argument::dir_OUT: + this->set_attribute (LITERALS[KIND], LITERALS[_OUT]); + break; + + default: + throw Error ("Unknown argument direction", node); + } + + this->set_containing_element (LITERALS[BFEATURE]); + + xid = this->lookup_type_xid (node->field_type ()); + this->set_attribute (LITERALS[TYPE], + xid); + + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + int + idl3_to_xmi_visitor::visit_attribute (AST_Attribute *node) + { + XMI_TRACE ("attribute"); + + if (this->skip_imported_ && node->imported ()) + { + return 0; + } + + if (this->cached_type_ == 0) + { + ACE_ERROR ((LM_ERROR, "Zounds! %d\n", + this->cached_type_)); + throw Error ("Internal error - attribute expected " + "to have a cached type, but didn't"); + } + + try + { + // *** + NS_Guard global_ns (ACE_TEXT ("::"), this); + ES_Guard assoc_group (this->associations_, this); + ES_Guard assoc_g (LITERALS[ASSOC_TAG], this); + + // I don't think anything else can refer to the attribute by + // xid, so I won't store it. + XStr xid = this->gen_xmi_id (node); + this->set_attribute (LITERALS[XMI_ID], xid); + this->set_attribute (LITERALS[VISIBIL], LITERALS[PUBLIC]); + this->set_containing_element (LITERALS[NS]); + if (node->readonly ()) + this->find_and_set_xid_as_attr (LITERALS[STEREO_ATTR], + LITERALS[ST_RO]); + + ES_Guard assoc_conn (LITERALS[ASSOC_CONN_TAG], this); + + { // Containing type + ES_Guard assoc_end (LITERALS[ASSOC_END_TAG], this); + this->set_attribute (LITERALS[MULT], ACE_TEXT ("1")); + this->find_and_set_xid_as_attr ( + LITERALS[TYPE], + ACE_TEXT_CHAR_TO_TCHAR (this->cached_type_->repoID ())); + } + + { + ES_Guard assoc_end (LITERALS[ASSOC_END_TAG], this); + this->set_attribute ( + LITERALS[NAME], + ACE_TEXT_CHAR_TO_TCHAR (node->original_local_name ()->get_string ())); + this->set_attribute (LITERALS[MULT], ACE_TEXT ("1")); + xid = this->lookup_type_xid (node->field_type ()); + this->set_attribute (LITERALS[TYPE], xid); + } + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + int + idl3_to_xmi_visitor::visit_union (AST_Union *node) + { + XMI_TRACE ("union"); + + if (this->skip_imported_ && node->imported ()) + { + return 0; + } + + try + { + DOMElement * ele = 0; + if (this->repo_id_map_.find (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele) != 0) + { + ES_Guard class_guard (LITERALS[CLASS_TAG], this); + + this->gen_common_elements (node, LITERALS[ST_UNION]); + + // Save in order not to generate same element later. + this->stack_.top (ele); + this->repo_id_map_.bind (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele); + } + + ES_Guard class_guard (ele, this); + NS_Guard ns_guard (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), this); + ES_Guard oe_guard (LITERALS[OWNEDELEMENT_TAG], this); + + // Set discriminator type + this->union_disc_ = node->disc_type (); + this->visit_scope (node); + this->union_disc_ = 0; + } + catch (Error &err) + { + this->union_disc_ = 0; + err.node (node); + throw; + } + + return 0; + } + + int + idl3_to_xmi_visitor::visit_union_fwd (AST_UnionFwd *node) + { + XMI_TRACE ("union_fwd"); + + try + { + DOMElement * ele = 0; + if (this->repo_id_map_.find (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele) != 0) + { + ES_Guard class_guard (LITERALS[CLASS_TAG], this); + + this->gen_common_elements (node, LITERALS[ST_UNION]); + + // Save in order not to generate same element later. + this->stack_.top (ele); + this->repo_id_map_.bind (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), ele); + } + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + int + idl3_to_xmi_visitor::visit_union_branch (AST_UnionBranch *node) + { + XMI_TRACE ("union_branch"); + + try + { + ES_Guard attr_guard (LITERALS[ATTR_TAG], this); + + // I don't think anything else can refer to the parameter by + // xid, so I won't store it. + XStr xid = this->gen_xmi_id (node); + this->set_attribute (LITERALS[XMI_ID], xid); + + // name + this->set_attribute ( + LITERALS[NAME], + ACE_TEXT_CHAR_TO_TCHAR (node->original_local_name ()->get_string ())); + + // visiblity + this->set_attribute (LITERALS[VISIBIL], LITERALS[PUBLIC]); + + this->set_containing_element (LITERALS[OWNER]); + + // I think this is fixed. + this->set_attribute (LITERALS[MULT], LITERALS[MULT_ZTO]); + + xid = this->lookup_type_xid (node->field_type ()); + this->set_attribute (LITERALS[TYPE], + xid); + + { + ES_Guard me_tv_guard (LITERALS[ME_TV_TAG], this); + + { + ES_Guard tv_guard (LITERALS[TV_TAG], this); + this->set_attribute (LITERALS[TAG], LITERALS[IDLORDER]); + + // convert the order value to a string + // need a buffer, with a little safety padding + ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> buffer + (this->number_to_string (this->order_)); + + this->set_attribute (LITERALS[VALUE], buffer.get ()); + } + + for (unsigned long i = 0; i < node->label_list_length (); ++i) + this->visit_union_label (node->label (i)); + + } + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + ACE_TCHAR * + idl3_to_xmi_visitor::union_label_value (AST_Expression *exp) + { + ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> buffer; + + // @@TODO: Yuck, there has got to be a better way.... + AST_Expression::AST_ExprValue *ev = exp->ev (); + + if (exp->ec () != AST_Expression::EC_symbol || + this->union_disc_->node_type () == AST_Decl::NT_typedef || + this->union_disc_->node_type () == AST_Decl::NT_pre_defined) + { + /*AST_Expression::ExprType type; + + if (this->union_disc_->node_type () == AST_Decl::NT_typedef) + { + AST_Typedef *td (AST_Typedef::narrow_from_decl (this->union_disc_)); + type = td->base_type ()->node_type (); + } + else type = ev->et;*/ + + // Decode the type + switch (ev->et) + { + case AST_Expression::EV_long: + buffer.reset (this->number_to_string (ev->u.lval)); + break; + case AST_Expression::EV_ulong: + buffer.reset (this->number_to_string (ev->u.ulval)); + break; + case AST_Expression::EV_short: + buffer.reset (this->number_to_string (ev->u.sval)); + break; + case AST_Expression::EV_ushort: + buffer.reset (this->number_to_string (ev->u.usval)); + break; + case AST_Expression::EV_bool: + buffer.reset (this->number_to_string (ev->u.bval)); + break; + case AST_Expression::EV_char: + buffer.reset (this->number_to_string (ev->u.cval)); + break; + default: + throw Error ("Unknown union union label type"); + } + } + else + { + AST_Enum *desc (0); + if ((desc = AST_Enum::narrow_from_decl (this->union_disc_)) == 0) + throw Error ("Descriminator type is not an enum"); + + AST_Decl *ev_decl = + desc->lookup_by_name (exp->n (), 1); + + if (ev_decl == 0) + throw Error ("Couldn't look up enum name"); + + AST_EnumVal *ev = AST_EnumVal::narrow_from_decl (ev_decl); + + if (ev == 0) + throw Error ("Couldn't look up enum name"); + + buffer.reset (ACE::strnew (ACE_TEXT_CHAR_TO_TCHAR (ev->full_name ()))); + //const char *name = desc->lookup_by_value (exp)->full_name (); + // const char *name = exp->n (); + //buffer.reset (copy_scoped_name (exp->n ())); + } + + if (buffer.get () == 0) + throw Error ("Unable to parse union label"); + + return buffer.release (); + } + + int + idl3_to_xmi_visitor::visit_union_label (AST_UnionLabel *node) + { + XMI_TRACE ("union_label"); + + ES_Guard tv_guard (LITERALS[TV_TAG], this); + this->set_attribute (LITERALS[TAG], LITERALS[CASE]); + + if (node->label_kind () == AST_UnionLabel::UL_default) + this->set_attribute (LITERALS[VALUE], LITERALS[DEFAULT_UNION]); + else + { + ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> + buffer (this->union_label_value (node->label_val ())); + + this->set_attribute (LITERALS[VALUE], buffer.get ()); + } + + return 0; + } + + int + idl3_to_xmi_visitor::visit_constant (AST_Constant *node) + { + XMI_TRACE ("constant"); + + if (this->skip_imported_ && node->imported ()) + { + return 0; + } + + try + { + ES_Guard attr_guard (LITERALS[ATTR_TAG], this); + + this->set_attribute (LITERALS[OWNER_SCOPE], LITERALS[CLASSIFIER]); + this->set_attribute (LITERALS[CHANGEABLE], LITERALS[FROZEN]); + this->gen_common_elements (node, LITERALS[ST_CONST]); + + // Constant type + const ACE_TCHAR *exprtype (0); + AST_Expression::AST_ExprValue *val + (node->constant_value ()->ev ()); + + ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> str_value; + + switch (node->et ()) + { + case AST_Expression::EV_short: + exprtype = LITERALS[ST_SHORT]; + str_value.reset (this->number_to_string (val->u.sval)); + break; + case AST_Expression::EV_ushort: + exprtype = LITERALS[ST_US]; + str_value.reset (this->number_to_string (val->u.usval)); + break; + case AST_Expression::EV_long: + exprtype = LITERALS[ST_LONG]; + str_value.reset (this->number_to_string (val->u.lval)); + break; + case AST_Expression::EV_ulong: + exprtype = LITERALS[ST_UL]; + str_value.reset (this->number_to_string (val->u.ulval)); + break; + case AST_Expression::EV_longlong: + exprtype = LITERALS[ST_LL]; + str_value.reset (this->number_to_string (val->u.llval)); + case AST_Expression::EV_ulonglong: + exprtype = LITERALS[ST_ULL]; + str_value.reset (this->number_to_string (val->u.ullval)); + break; + case AST_Expression::EV_float: + exprtype = LITERALS[ST_FLOAT]; + str_value.reset (this->number_to_string (val->u.fval)); + break; + case AST_Expression::EV_double: + exprtype = LITERALS[ST_DOUBLE]; + str_value.reset (this->number_to_string (val->u.dval)); + break; + case AST_Expression::EV_longdouble: + exprtype = LITERALS[ST_LD]; + str_value.reset (this->number_to_string (val->u.dval)); + break; + case AST_Expression::EV_char: + exprtype = LITERALS[ST_CHAR]; + str_value.reset (this->number_to_string (val->u.cval)); + break; + case AST_Expression::EV_wchar: + exprtype = LITERALS[ST_WCHAR]; + str_value.reset (this->number_to_string (val->u.wcval)); + break; + case AST_Expression::EV_octet: + exprtype = LITERALS[ST_OCTET]; + str_value.reset (this->number_to_string (val->u.dval)); + break; + case AST_Expression::EV_bool: + exprtype = LITERALS[ST_BOOL]; + str_value.reset (this->number_to_string (val->u.bval)); + break; + case AST_Expression::EV_string: + exprtype = LITERALS[ST_STR]; + str_value.reset (ACE::strnew ( + ACE_TEXT_CHAR_TO_TCHAR (val->u.strval->get_string ()))); + break; + case AST_Expression::EV_wstring: + exprtype = LITERALS[ST_WSTR]; + str_value.reset (ACE::strnew ( + ACE_TEXT_CHAR_TO_TCHAR (val->u.wstrval))); + break; + case AST_Expression::EV_enum: + { + UTL_Scope *s = node->defined_in (); + AST_Decl *d = + s->lookup_by_name (node->constant_value ()->n (), 1); + exprtype = ACE_TEXT_CHAR_TO_TCHAR ( + ScopeAsDecl (d->defined_in ())->repoID ()); + str_value.reset (ACE::strnew ( + ACE_TEXT_CHAR_TO_TCHAR (d->full_name ()))); + } + break; + + default: + throw Error ("Unsupported constant type", node); + } + + // type attribute + XStr xid (this->lookup_xid (exprtype)); + this->set_attribute (LITERALS[TYPE], + xid); + + { + ES_Guard me_tv (LITERALS[ME_TV_TAG], this); + { + ES_Guard tv (LITERALS[TV_TAG], this); + this->set_attribute (LITERALS[TAG], LITERALS[INIT_VAL]); + this->set_attribute (LITERALS[VALUE], str_value.get ()); + } + } + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + int + idl3_to_xmi_visitor::visit_enum_val (AST_EnumVal *node) + { + XMI_TRACE ("enum val"); + + if (this->skip_imported_ && node->imported ()) + { + return 0; + } + + if (!this->visiting_enum_) + { + // It makes sence only to process enumvals in enum "scope". + return 0; + } + + try + { + ES_Guard att_guard (LITERALS[ATTR_TAG], this); + + this->create_and_store_xmi_id ( + ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), + node); + this->set_attribute ( + LITERALS[NAME], + ACE_TEXT_CHAR_TO_TCHAR (node->original_local_name ()->get_string ())); + + // I think this is fixed. + this->set_attribute (LITERALS[MULT], LITERALS[MULT_OTO]); + this->set_containing_element (LITERALS[OWNER]); + + ES_Guard me_guard (LITERALS[ME_TV_TAG], this); + ES_Guard tv_guard (LITERALS[TV_TAG], this); + + this->set_attribute (LITERALS[TAG], LITERALS[IDLORDER]); + + // convert the enum value to a string + // need a buffer, with a little safety padding + + ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> buffer + (this->number_to_string (node->constant_value ()->ev ()->u.eval)); + + this->set_attribute (LITERALS[VALUE], buffer.get ()); + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + int + idl3_to_xmi_visitor::visit_array (AST_Array *node) + { + XMI_TRACE ("array val"); + + if (this->skip_imported_ && node->imported ()) + { + return 0; + } + + try + { + this->gen_common_elements (node, + LITERALS[ST_ARR]); + + this->gen_array_associations (node, node); + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + void + idl3_to_xmi_visitor::gen_array_associations (AST_Decl *node, + AST_Array *array) + { + // <UML:Namespace.ownedElement> + NS_Guard global_ns (ACE_TEXT ("::"), this); + + // <UML:Association xmi.id="xmi.1210085542354" + // visibility="public" namespace="xmi.1210085542350"> + ES_Guard assoc_group (this->associations_, this); + ES_Guard assoc_g (LITERALS[ASSOC_TAG], this); + + XStr xid = this->gen_xmi_id (node); + this->set_attribute (LITERALS[XMI_ID], xid); + this->set_attribute (LITERALS[VISIBIL], LITERALS[PUBLIC]); + this->set_containing_element (LITERALS[NS]); + + // <UML:Association.connection> + ES_Guard assoc_conn (LITERALS[ASSOC_CONN_TAG], this); + + { + // <UML:AssociationEnd multiplicity="0..1" type="xmi.1210085542353"> + ES_Guard assocend (LITERALS[ASSOC_END_TAG], this); + + this->set_attribute (LITERALS[MULT], LITERALS[MULT_ZTO]); + + xid = this->lookup_xid (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ())); + this->set_attribute (LITERALS[TYPE], xid); + + // <UML:AssociationEnd.qualifier> + ES_Guard assoc_qual (LITERALS[ASSOC_END_QUAL_TAG], this); + + for (unsigned long i = 0; + array != 0 && i < array->n_dims (); + ++i) + { + // <UML:Attribute xmi.id="xmi.1210085542355" + // name="index0" type='xmi.1210085542329'> + // N.B. that type is long. + ES_Guard attr (LITERALS[ATTR_TAG], this); + + xid = this->gen_xmi_id (node); + this->set_attribute (LITERALS[XMI_ID], xid); + + std::stringstream str; + str << LITERALS[INDEX]; + str << i; + + this->set_attribute ( + LITERALS[NAME], + ACE_TEXT_CHAR_TO_TCHAR (str.str ().c_str ())); + xid = this->lookup_xid (LITERALS[ST_LONG]); + this->set_attribute (LITERALS[TYPE], xid); + + // <UML:ModelElement.constraint> + ES_Guard me_c (LITERALS[ME_CONS_TAG], this); + + // <UML:Constraint xmi.id="xmi.1210085542356"> + ES_Guard cons (LITERALS[CONSTRAINT], this); + + xid = this->gen_xmi_id (node); + this->set_attribute (LITERALS[XMI_ID], xid); + + // <UML:ModelElement.taggedValue> + ES_Guard me_tv (LITERALS[ME_TV_TAG], this); + + // <UML:TaggedValue tag="constraintUpperValue" value="4"/> + ES_Guard tv (LITERALS[TV_TAG], this); + + this->set_attribute (LITERALS[TAG], LITERALS[CONST_UPPER]); + + ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> buffer ( + this->number_to_string (array->dims ()[i]->ev ()->u.ulval)); + + this->set_attribute (LITERALS[VALUE], buffer.get ()); + } + } + + // <UML:AssociationEnd multiplicity="1..1" + // type="xmi.1210085542346"/> - type is Char for this IDL + ES_Guard assoc_end (LITERALS[ASSOC_END_TAG], this); + this->set_attribute (LITERALS[MULT], LITERALS[MULT_OTO]); + + XStr arr_type = this->lookup_type_xid (array->base_type ()); + this->set_attribute (LITERALS[TYPE], arr_type); + } + + int + idl3_to_xmi_visitor::visit_sequence (AST_Sequence *node) + { + XMI_TRACE ("sequence val"); + + if (this->skip_imported_ && node->imported ()) + { + return 0; + } + + try + { + this->gen_common_elements (node, + LITERALS[ST_SEQ]); + + // Generate the bounds and type on the sequence, which is an + // association in the association tree. + this->gen_sequence_associations (node, node); + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + void + idl3_to_xmi_visitor::gen_sequence_associations (AST_Decl *node, + AST_Sequence *sequence) + { + // <UML:Namespace.ownedElement> + NS_Guard global_ns (ACE_TEXT ("::"), this); + + // <UML:Association xmi.id="xmi.1210085542354" + // visibility="public" namespace="xmi.1210085542350"> + ES_Guard assoc_group (this->associations_, this); + ES_Guard assoc_g (LITERALS[ASSOC_TAG], this); + + XStr xid = this->gen_xmi_id (node); + this->set_attribute (LITERALS[XMI_ID], xid); + this->set_attribute (LITERALS[VISIBIL], LITERALS[PUBLIC]); + this->set_containing_element (LITERALS[NS]); + + // <UML:Association.connection> + ES_Guard assoc_conn (LITERALS[ASSOC_CONN_TAG], this); + + { + // <UML:AssociationEnd multiplicity="0..1" type="xmi.1210085542353"> + ES_Guard assocend (LITERALS[ASSOC_END_TAG], this); + + this->set_attribute (LITERALS[MULT], LITERALS[MULT_ZTO]); + + xid = this->lookup_xid (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ())); + this->set_attribute (LITERALS[TYPE], xid); + + // <UML:AssociationEnd.qualifier> + ES_Guard assoc_qual (LITERALS[ASSOC_END_QUAL_TAG], this); + + ES_Guard attr (LITERALS[ATTR_TAG], this); + + xid = this->gen_xmi_id (node); + this->set_attribute (LITERALS[XMI_ID], xid); + this->set_attribute (LITERALS[NAME], LITERALS[INDEX]); + xid = this->lookup_xid (LITERALS[ST_LONG]); + this->set_attribute (LITERALS[TYPE], xid); + + ES_Guard me_c (LITERALS[ME_CONS_TAG], this); + ES_Guard cons (LITERALS[CONSTRAINT], this); + ES_Guard me_tv (LITERALS[ME_TV_TAG], this); + ES_Guard tv (LITERALS[TV_TAG], this); + + this->set_attribute (LITERALS[TAG], LITERALS[CONST_UPPER]); + + // @@TODO: need to extract bound from node. + if (sequence->unbounded ()) + { + this->set_attribute (LITERALS[VALUE], + LITERALS[UNBOUNDED_SEQ]); + } + else + { // bounded sequence + // convert the array bound to a string + // need a buffer, with a little safety padding + ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> buffer ( + this->number_to_string (sequence->max_size ()->ev ()->u.ulval)); + + this->set_attribute (LITERALS[VALUE], buffer.get ()); + } + } + + // <UML:AssociationEnd multiplicity="1..1" + // type="xmi.1210085542346"/> - type is Char for this IDL + ES_Guard assoc_end (LITERALS[ASSOC_END_TAG], this); + this->set_attribute (LITERALS[MULT], LITERALS[MULT_OTO]); + + XStr seq_type = this->lookup_type_xid (sequence->base_type ()); + this->set_attribute (LITERALS[TYPE], seq_type); + } + + int + idl3_to_xmi_visitor::visit_string (AST_String *) + { + XMI_TRACE ("string"); + return 0; + } + + int + idl3_to_xmi_visitor::visit_typedef (AST_Typedef *node) + { + XMI_TRACE ("typedef"); + + if (this->skip_imported_ && node->imported ()) + { + return 0; + } + + try + { + ES_Guard class_guard (LITERALS[CLASS_TAG], this); + + // Anonymous Sequences and arrays appear to be a special case + AST_Decl *base (node->base_type ()); + if (base->node_type () == AST_Decl::NT_sequence) + { + this->gen_common_elements (node, LITERALS[ST_SEQ]); + + AST_Sequence* sequence = + AST_Sequence::narrow_from_decl (base); + this->gen_sequence_associations (node, sequence); + } + else if (base->node_type () == AST_Decl::NT_array) + { + this->gen_common_elements (node, LITERALS[ST_ARR]); + + AST_Array* array = + AST_Array::narrow_from_decl (base); + this->gen_array_associations (node, array); + } + else + { + this->gen_common_elements (node, + LITERALS[ST_TYPEDEF]); + + // Generalization. Assignment required for memory management. + XStr xid = this->add_generalization (node, + node->base_type ()); + ACE_UNUSED_ARG (xid); + } + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + int + idl3_to_xmi_visitor::visit_root (AST_Root *node) + { + XMI_TRACE ("root"); + try + { + ACE_CString fn; + + if ((fn = be_global->filename ()) == "") + { + fn = idl_global->stripped_filename ()->get_string (); + fn = fn.substr (0, fn.rfind ('.')); + fn += ".xmi"; + } + + const char *path = be_global->output_dir (); + ACE_CString target_name; + + if (path != 0) + { + target_name = path; + target_name += "/"; + } + + target_name += fn; + + CIAO::XML::NoOp_Resolver res_func; + CIAO::XML::XML_Schema_Resolver<> resolver (res_func); + CIAO::XML::XML_Error_Handler handler; + CIAO::XML::XML_Helper<> helper (resolver, handler); + + // Create XML document + std::auto_ptr<DOMDocumentType> doctype ( + helper.create_doctype (ACE_TEXT("XMI"), + 0, + ACE_TEXT_CHAR_TO_TCHAR (be_global->dtd ()))); + + if ((this->dom_ = helper.create_dom (ACE_TEXT("XMI"), + ACE_TEXT(""), + doctype.get ())) == 0) + ACE_ERROR_RETURN ((LM_ERROR, "Unable to create XML document."), -1); + + this->root_ = this->dom_->getDocumentElement (); + + this->stack_.push (this->root_); + + this->set_attribute (LITERALS[VERSION_TAG], + LITERALS[VERSION_VALUE]); + + this->set_attribute (LITERALS[NS_TAG], + LITERALS[NS_VALUE]); + + DOMElement *tmp = 0; + + // Pregenerate stereotypes to cache xmi.ids. + DOMElement *stereotypes = this->generate_stereotypes (); + + // Create XMI header + { + ES_Guard ht_g (LITERALS[HEADER_TAG], this); + ES_Guard d_t (LITERALS[DOC_TAG], this); + ES_Guard e_t (LITERALS[EXPORTER_TAG], this); + this->add_text (LITERALS[EXPORTER_VALUE]); + } + + this->stack_.push (this->create_element (LITERALS[CONTENT_TAG])); + this->stack_.push (this->create_element (LITERALS[MODEL_TAG])); + + // Store the base model xid + this->set_attribute (LITERALS[XMI_ID], this->base_id_); + this->id_map_.bind (ACE_TEXT ("::"), this->base_id_); + + + // Global namespace + this->stack_.push (this->create_element (LITERALS[OWNEDELEMENT_TAG])); + this->namespace_.push (ACE_TEXT ("::")); + + // Create generalizations and associations elements, but don't join + // them to the tree yet + this->associations_ = + this->dom_->createElement (XStr (LITERALS[OWNEDELEMENT_TAG])); + this->generalizations_ = + this->dom_->createElement (XStr (LITERALS[OWNEDELEMENT_TAG])); + + if (this->visit_scope (node) != 0) + { + ACE_ERROR_RETURN ((LM_ERROR, + "idl3_to_idl2_visitor::visit_root - " + "codegen for scope failed\n"), + -1); + } + + this->stack_.pop (tmp); + + this->stack_.top (tmp); + + tmp->appendChild (this->generalizations_); + tmp->appendChild (this->associations_); + tmp->appendChild (stereotypes); + + helper.write_DOM (this->dom_, + ACE_TEXT_CHAR_TO_TCHAR (target_name.c_str ())); + } + catch (const Error &ex) + { + if (ex.node_ != 0) + ACE_ERROR ((LM_ERROR, "%s:%d:error: %s\n", + ex.node_->file_name ().c_str (), + ex.node_->line (), + ex.diag_.c_str ())); + else + ACE_ERROR ((LM_ERROR, "::error:%s\n", + ex.diag_.c_str ())); + + return -1; + } + return 0; + } + + int + idl3_to_xmi_visitor::visit_native (AST_Native *node) + { + XMI_TRACE ("native"); + + if (this->skip_imported_ && node->imported ()) + { + return 0; + } + + try + { + ES_Guard class_guard (LITERALS[CLASS_TAG], this); + + this->gen_common_elements (node, LITERALS[ST_NATIVE]); + } + catch (Error &err) + { + err.node (node); + throw; + } + + return 0; + } + + void + idl3_to_xmi_visitor::set_attribute (const ACE_TCHAR *name, + const ACE_TCHAR *value) + { + DOMElement *ele = 0; + this->stack_.top (ele); + + ele->setAttribute (XStr (name), XStr (value)); + } + + + void + idl3_to_xmi_visitor::set_attribute (const ACE_TCHAR *name, + const XMLCh *value) + { + DOMElement *ele = 0; + this->stack_.top (ele); + + ele->setAttribute (XStr (name), value); + } + + void + idl3_to_xmi_visitor::add_text (const ACE_TCHAR *text) + { + DOMElement *ele = 0; + this->stack_.top (ele); + + DOMText *node = this->dom_->createTextNode (XStr (text)); + ele->appendChild (node); + } + + DOMElement * + idl3_to_xmi_visitor::create_element (const ACE_TCHAR *name) + { + DOMElement *ele = 0; + this->stack_.top (ele); + + DOMElement *node = this->dom_->createElement (XStr (name)); + + ele->appendChild (node); + + return node; + } + + DOMElement * + idl3_to_xmi_visitor::generate_stereotypes (void) + { + DOMElement *retval = + this->dom_->createElement (XStr (LITERALS[OWNEDELEMENT_TAG])); + + // put it on the stack to subsequent create_element calls refer to it. + this->stack_.push (retval); + + this->add_stereotype (ST_CONSUMES, ASSOC); + this->add_stereotype (ST_ANON_SEQ, CLASS); + this->add_stereotype (ST_PRINC, DATATYPE); + this->add_stereotype (ST_UNION, CLASS); + this->add_stereotype (ST_USES, ASSOC); + this->add_stereotype (ST_SEQ, CLASS); + this->add_stereotype (ST_ROE, __NULL); + this->add_stereotype (ST_RO, __NULL); + this->add_stereotype (ST_OBJ, DATATYPE); + this->add_stereotype (ST_STR, DATATYPE); + this->add_stereotype (ST_LD, DATATYPE); + this->add_stereotype (ST_ANON_ARR, CLASS); + this->add_stereotype (ST_ALIAS, CLASS); + this->add_stereotype (ST_NULL, DATATYPE); + this->add_stereotype (ST_VALUE, CLASS); + this->add_stereotype (ST_VOID, DATATYPE); + this->add_stereotype (ST_EX, CLASS); + this->add_stereotype (ST_OCTET, DATATYPE); + this->add_stereotype (ST_MANAGES, ASSOC); + this->add_stereotype (ST_WSTR, DATATYPE); + this->add_stereotype (ST_FLOAT, DATATYPE); + this->add_stereotype (ST_ENUM, CLASS); + this->add_stereotype (ST_VAL_SUP, CLASS); + this->add_stereotype (ST_MODULE, PACKAGE); + this->add_stereotype (ST_HFINDER, CLASS); + this->add_stereotype (ST_DOUBLE, DATATYPE); + this->add_stereotype (ST_LL, DATATYPE); + this->add_stereotype (ST_HFACT, CLASS); + this->add_stereotype (ST_ARR, CLASS); + this->add_stereotype (ST_COMP, CLASS); + this->add_stereotype (ST_SHORT, DATATYPE); + this->add_stereotype (ST_TYPEDEF, CLASS); + this->add_stereotype (ST_ULL, DATATYPE); + this->add_stereotype (ST_LONG, DATATYPE); + this->add_stereotype (ST_TC, DATATYPE); + this->add_stereotype (ST_HOME, CLASS); + this->add_stereotype (ST_STRUCT, CLASS); + this->add_stereotype (ST_FIXED, DATATYPE); + this->add_stereotype (ST_US, DATATYPE); + this->add_stereotype (ST_EMITS, ASSOC); + this->add_stereotype (ST_BOXVALUE, CLASS); + this->add_stereotype (ST_BOOL, DATATYPE); + this->add_stereotype (ST_CONST, ATTR); + this->add_stereotype (ST_PUBLISH, ASSOC); + this->add_stereotype (ST_CONSTANTS, CLASS); + this->add_stereotype (ST_PROVIDES, ASSOC); + this->add_stereotype (ST_WCHAR, DATATYPE); + this->add_stereotype (ST_UL, DATATYPE); + this->add_stereotype (ST_VAL_FACT, CLASS); + this->add_stereotype (ST_EVENT, CLASS); + this->add_stereotype (ST_CHAR, DATATYPE); + this->add_stereotype (ST_INTF, CLASS); + this->add_stereotype (ST_PRI_KEY, CLASS); + this->add_stereotype (ST_ANY, DATATYPE); + this->add_stereotype (ST_NATIVE, CLASS); + + this->stack_.pop (retval); + + return retval; + } + + void + idl3_to_xmi_visitor::add_stereotype (const LITERAL_T name, + const LITERAL_T bc) + { + // Generate our xmi.id + XStr xid (this->gen_xmi_id ()); + + // Bind the id in the map + this->id_map_.bind (LITERALS[name], xid); + + DOMElement *ele = this->create_element (LITERALS[STEREOTYPE_TAG]); + ele->setAttribute (XStr (LITERALS[XMI_ID]), xid); + ele->setAttribute (XStr (LITERALS[NAME]), XStr (LITERALS[name])); + ele->setAttribute (XStr (LITERALS[BASEC]), XStr (LITERALS[bc])); + + return; + } + + XMLCh * + idl3_to_xmi_visitor::gen_xmi_id (const ACE_TCHAR *name, long line) + { + if (current_id_ == 0) + { + ACE_OS::srand (ACE_OS::gettimeofday ().msec ()); + current_id_ = rand (); + } + std::stringstream str; + // Skip all characters that cannot be a first name char in xmi.id. + while (name && *name && !XMLChar1_1::isFirstNameChar(*name)) ++name; + // Since we use a file path as name then let's change all non-name + // chars for '_'. + while (name && *name) + { + if (XMLChar1_1::isNameChar (*name)) + { + str << *name; + } + else + { + str << '_'; + } + ++name; + } + str << ':' << line << '.' << current_id_++; + + XStr retval (ACE_TEXT_CHAR_TO_TCHAR (str.str ().c_str ())); + return retval.release (); + + } + + XMLCh * + idl3_to_xmi_visitor::gen_xmi_id (AST_Decl *node) + { + if (current_id_ == 0) + { + ACE_OS::srand (ACE_OS::gettimeofday ().msec ()); + current_id_ = rand (); + } + + // we want these IDs to be unique, but the CDMW code generator sometimes depends + // on the order these things were declared in IDL, so for cases like that, + // we generate an ID that will sort to the order it was declared in IDL, + // no matter which order we visit the nodes. + if (node != 0) + return gen_xmi_id (ACE_TEXT_CHAR_TO_TCHAR (node->file_name ().c_str ()), + node->line ()); + + std::stringstream str; + + str << "xmi." << current_id_++; + XStr retval (ACE_TEXT_CHAR_TO_TCHAR (str.str ().c_str ())); + return retval.release (); + } + + void + idl3_to_xmi_visitor::set_containing_element (const ACE_TCHAR *cont_name) + { + ACE_TString tmp; + XStr xid; + + this->namespace_.top (tmp); + this->id_map_.find (tmp, xid); + this->set_attribute (cont_name, xid); + } + + void + idl3_to_xmi_visitor::create_and_store_xmi_id (AST_Decl *node) + { + try + { + this->create_and_store_xmi_id ( + ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), node); + } + catch (Error &ex) + { + ex.node (node); + throw; + } + } + + void + idl3_to_xmi_visitor::create_and_store_xmi_id ( + const ACE_TCHAR *name, AST_Decl *node) + { + XStr xid = this->gen_xmi_id (node); + + // store xmi_id + if (this->id_map_.trybind (name, xid) == -1) + throw Error ("error binding in the XMI ID map"); + + this->set_attribute (LITERALS[XMI_ID], xid); + } + + XMLCh * + idl3_to_xmi_visitor::lookup_xid (const ACE_TCHAR *name) + { + XStr tmp; + if (this->id_map_.find (name, tmp) == -1) + { + ACE_CString err ("unknown XMI ID requested for "); + err += ACE_TEXT_ALWAYS_CHAR (name); + throw Error (err.c_str ()); + } + + return tmp.release (); + } + + XMLCh * + idl3_to_xmi_visitor::lookup_type_xid (AST_Type *node) + { + AST_PredefinedType *pdt = 0; + + switch (node->node_type ()) + { + case AST_Decl::NT_string: + return this->lookup_xid (LITERALS[ST_STR]); + case AST_Decl::NT_wstring: + return this->lookup_xid (LITERALS[ST_WSTR]); + + case AST_Decl::NT_pre_defined: + pdt = AST_PredefinedType::narrow_from_decl (node); + + switch (pdt->pt ()) + { + case AST_PredefinedType::PT_pseudo: + return this->lookup_xid (ACE_TEXT_CHAR_TO_TCHAR (pdt->repoID ())); + case AST_PredefinedType::PT_object: + return this->lookup_xid (LITERALS[ST_OBJ]); + case AST_PredefinedType::PT_any: + return this->lookup_xid (LITERALS[ST_ANY]); + case AST_PredefinedType::PT_long: + return this->lookup_xid (LITERALS[ST_LONG]); + case AST_PredefinedType::PT_ulong: + return this->lookup_xid (LITERALS[ST_UL]); + case AST_PredefinedType::PT_longlong: + return this->lookup_xid (LITERALS[ST_LL]); + case AST_PredefinedType::PT_ulonglong: + return this->lookup_xid (LITERALS[ST_ULL]); + case AST_PredefinedType::PT_short: + return this->lookup_xid (LITERALS[ST_SHORT]); + case AST_PredefinedType::PT_ushort: + return this->lookup_xid (LITERALS[ST_US]); + case AST_PredefinedType::PT_float: + return this->lookup_xid (LITERALS[ST_FLOAT]); + case AST_PredefinedType::PT_double: + return this->lookup_xid (LITERALS[ST_DOUBLE]); + case AST_PredefinedType::PT_longdouble: + return this->lookup_xid (LITERALS[ST_LD]); + case AST_PredefinedType::PT_char: + return this->lookup_xid (LITERALS[ST_CHAR]); + case AST_PredefinedType::PT_wchar: + return this->lookup_xid (LITERALS[ST_WCHAR]); + case AST_PredefinedType::PT_boolean: + return this->lookup_xid (LITERALS[ST_BOOL]); + case AST_PredefinedType::PT_octet: + return this->lookup_xid (LITERALS[ST_OCTET]); + case AST_PredefinedType::PT_void: + return this->lookup_xid (LITERALS[ST_VOID]); + default: + throw Error ("Unknown or unsupported predefined type", + pdt); + } + default: + return this->lookup_xid (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ())); + } + } + + void + idl3_to_xmi_visitor::find_and_set_xid_as_attr (const ACE_TCHAR *attr_name, + const ACE_TCHAR *xid_name) + { + XStr tmp; + + if (this->id_map_.find (xid_name, tmp) == -1) + { + ACE_CString err ("unknown XMI ID when looking up "); + err += ACE_TEXT_ALWAYS_CHAR (xid_name); + throw Error (err.c_str ()); + } + + this->set_attribute (attr_name, tmp); + } + + void + idl3_to_xmi_visitor::gen_tagged_value (AST_Decl *node) + { + ES_Guard me_guard (LITERALS[ME_TV_TAG], this); + ES_Guard tv_guard (LITERALS[TV_TAG], this); + + this->set_attribute (LITERALS[TAG], LITERALS[TYPEID]); + this->set_attribute (LITERALS[VALUE], + ACE_TEXT_CHAR_TO_TCHAR (node->repoID ())); + } + + XMLCh * + idl3_to_xmi_visitor::add_generalization (const ACE_TCHAR *sub, + const ACE_TCHAR *super) + { + return this->add_generalization (XStr (this->lookup_xid (sub)), + XStr (this->lookup_xid (super))); + } + + XMLCh * + idl3_to_xmi_visitor::add_generalization (AST_Type *sub, AST_Type *super) + { + return this->add_generalization (XStr (this->lookup_type_xid (sub)), + XStr (this->lookup_type_xid (super))); + } + + XMLCh * + idl3_to_xmi_visitor::add_generalization (const XMLCh *sub, + const XMLCh *super) + { + // Generate XMI ID + XStr xid (this->gen_xmi_id ()); + + { // add generalization to the 'generalizations' set + ES_Guard es_guard (this->generalizations_, this); + NS_Guard ns_guard (ACE_TEXT ("::"), this); + + ES_Guard gen_guard (LITERALS[GEN_TAG], this); + + this->set_attribute (LITERALS[XMI_ID], xid); + + this->set_containing_element (LITERALS[NS]); + + { // subtype + ES_Guard st_guard (LITERALS[GEN_SUB_TAG], this); + ES_Guard element_guard (LITERALS[GEN_ELEMENT_TAG], this); + + this->set_attribute (LITERALS[IDREF], sub); + } + + { // subtype + ES_Guard st_guard (LITERALS[GEN_SUPER_TAG], this); + ES_Guard element_guard (LITERALS[GEN_ELEMENT_TAG], this); + + this->set_attribute (LITERALS[IDREF], super); + } + } + + { // Reference generalization in the calling element. + ES_Guard et_g (LITERALS[GEN_ELEMENT_GEN_TAG], this); + ES_Guard g_g (LITERALS[GEN_TAG], this); + this->set_attribute (LITERALS[IDREF], xid); + } + + return xid.release (); + } + + void + idl3_to_xmi_visitor::add_port (const ACE_TCHAR *component, + const ACE_TCHAR *port_kind, + const ACE_TCHAR *port_type, + const ACE_TCHAR *name, + bool is_multiple, + const ACE_TCHAR *file_name, + long line) + { + if (is_multiple) + throw Error ("uses multiple not yet supported."); + + ES_Guard es_guard (this->associations_, this); + NS_Guard ns_guard (ACE_TEXT ("::"), this); + + ES_Guard assoc_guard (LITERALS[ASSOC_TAG], this); + + // Generate XMI ID + XStr xid (this->gen_xmi_id (file_name, line)); + this->set_attribute (LITERALS[XMI_ID], xid); + this->set_attribute (LITERALS[VISIBIL], LITERALS[PUBLIC]); + this->find_and_set_xid_as_attr (LITERALS[STEREO_ATTR], port_kind); + this->set_containing_element (LITERALS[NS]); + + ES_Guard conn_guard (LITERALS[ASSOC_CONN_TAG], this); + + { // component end + ES_Guard end_guard (LITERALS[ASSOC_END_TAG], this); + this->set_attribute (LITERALS[MULT], ACE_TEXT ("1")); + this->find_and_set_xid_as_attr (LITERALS[TYPE], component); + } + + { // component end + ES_Guard end_guard (LITERALS[ASSOC_END_TAG], this); + this->set_attribute (LITERALS[NAME], name); + this->set_attribute (LITERALS[MULT], ACE_TEXT ("1")); + this->find_and_set_xid_as_attr (LITERALS[TYPE], port_type); + } + } + + void + idl3_to_xmi_visitor::add_managed_component (const ACE_TCHAR *home, + const ACE_TCHAR *component) + { + ES_Guard es_guard (this->associations_, this); + NS_Guard ns_guard (ACE_TEXT ("::"), this); + + ES_Guard assoc_guard (LITERALS[ASSOC_TAG], this); + + // Generate XMI ID + XStr xid (this->gen_xmi_id ()); + this->set_attribute (LITERALS[XMI_ID], xid); + this->set_attribute (LITERALS[VISIBIL], LITERALS[PUBLIC]); + this->find_and_set_xid_as_attr (LITERALS[STEREO_ATTR], + LITERALS[ST_MANAGES]); + this->set_containing_element (LITERALS[NS]); + + ES_Guard conn_guard (LITERALS[ASSOC_CONN_TAG], this); + + { // home end + ES_Guard end_guard (LITERALS[ASSOC_END_TAG], this); + this->find_and_set_xid_as_attr (LITERALS[STEREO_ATTR], + LITERALS[ST_HOME]); + this->find_and_set_xid_as_attr (LITERALS[TYPE], home); + } + + { // component end + ES_Guard end_guard (LITERALS[ASSOC_END_TAG], this); + this->find_and_set_xid_as_attr (LITERALS[STEREO_ATTR], + LITERALS[ST_COMP]); + this->find_and_set_xid_as_attr (LITERALS[TYPE], component); + } + } + + void + idl3_to_xmi_visitor::gen_common_elements (AST_Decl *node, + const ACE_TCHAR *stereotype) + { + this->create_and_store_xmi_id (node); + this->set_attribute ( + LITERALS[NAME], + ACE_TEXT_CHAR_TO_TCHAR (node->original_local_name ()->get_string ())); + this->set_attribute (LITERALS[VISIBIL], LITERALS[PUBLIC]); + this->set_containing_element (LITERALS[NS]); + this->find_and_set_xid_as_attr (LITERALS[STEREO_ATTR], + stereotype); + + NS_Guard ns_guard (ACE_TEXT_CHAR_TO_TCHAR (node->repoID ()), this); + this->gen_tagged_value (node); + } + + void + idl3_to_xmi_visitor::gen_component_ports (PORTS &ports, + const ACE_TCHAR *component, + const ACE_TCHAR *port_kind, + const ACE_TCHAR *file_name) + { + for (size_t i = 0; i < ports.size (); ++i) + { + AST_Component::port_description *pd = 0; + ports.get (pd, i); + this->add_port (component, + port_kind, + ACE_TEXT_CHAR_TO_TCHAR (pd->impl->repoID ()), + ACE_TEXT_CHAR_TO_TCHAR (IdentifierHelper::original_local_name (pd->id)->get_string ()), + pd->is_multiple, + file_name, + pd->line_number); + } + } + + idl3_to_xmi_visitor::ES_Guard::ES_Guard (const ACE_TCHAR *name, + idl3_to_xmi_visitor *vis) + : vis_ (*vis) + { + if (vis_.stack_.push (vis_.create_element (name))) + throw Error ("element stack error"); + } + + idl3_to_xmi_visitor::ES_Guard::ES_Guard (DOMElement *ele, + idl3_to_xmi_visitor *vis) + : vis_ (*vis) + { + if (vis_.stack_.push (ele) != 0) + throw Error ("element stack error"); + } + + idl3_to_xmi_visitor::ES_Guard::~ES_Guard (void) + { + DOMElement *tmp; + if (vis_.stack_.pop (tmp) != 0) + { + vis_.output_dirty_ = true; + ACE_ERROR ((LM_ERROR, "error: element stack underflow.")); + } + } + + idl3_to_xmi_visitor::NS_Guard::NS_Guard (const ACE_TCHAR *name, + idl3_to_xmi_visitor *vis) + : vis_ (*vis) + { + int res = vis_.namespace_.push (name); + + if (res == 0) return; + throw Error ("stack error"); + } + + idl3_to_xmi_visitor::NS_Guard::~NS_Guard (void) + { + ACE_TString tmp; + if (vis_.namespace_.pop (tmp) != 0) + { + vis_.output_dirty_ = true; + ACE_ERROR ((LM_ERROR, "error:namespace stack underflow")); + } + } + } +} |