choicestr.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:55k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: choicestr.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 19:42:27  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.50
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: choicestr.cpp,v 1000.2 2004/06/01 19:42:27 gouriano Exp $
  10. * ===========================================================================
  11. *
  12. *                            PUBLIC DOMAIN NOTICE
  13. *               National Center for Biotechnology Information
  14. *
  15. *  This software/database is a "United States Government Work" under the
  16. *  terms of the United States Copyright Act.  It was written as part of
  17. *  the author's official duties as a United States Government employee and
  18. *  thus cannot be copyrighted.  This software/database is freely available
  19. *  to the public for use. The National Library of Medicine and the U.S.
  20. *  Government have not placed any restriction on its use or reproduction.
  21. *
  22. *  Although all reasonable efforts have been taken to ensure the accuracy
  23. *  and reliability of the software and data, the NLM and the U.S.
  24. *  Government do not and cannot warrant the performance or results that
  25. *  may be obtained by using this software or data. The NLM and the U.S.
  26. *  Government disclaim all warranties, express or implied, including
  27. *  warranties of performance, merchantability or fitness for any particular
  28. *  purpose.
  29. *
  30. *  Please cite the author in any work or product based on this material.
  31. *
  32. * ===========================================================================
  33. *
  34. * Author: Eugene Vasilchenko
  35. *
  36. * File Description:
  37. *   Type info for class generation: includes, used classes, C code etc.
  38. *
  39. * ---------------------------------------------------------------------------
  40. * $Log: choicestr.cpp,v $
  41. * Revision 1000.2  2004/06/01 19:42:27  gouriano
  42. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.50
  43. *
  44. * Revision 1.50  2004/05/17 21:03:13  gorelenk
  45. * Added include of PCH ncbi_pch.hpp
  46. *
  47. * Revision 1.49  2004/05/03 19:31:03  gouriano
  48. * Made generation of DOXYGEN-style comments optional
  49. *
  50. * Revision 1.48  2004/04/29 20:11:40  gouriano
  51. * Generate DOXYGEN-style comments in C++ headers
  52. *
  53. * Revision 1.47  2003/11/20 14:32:40  gouriano
  54. * changed generated C++ code so NULL data types have no value
  55. *
  56. * Revision 1.46  2003/10/21 13:48:51  grichenk
  57. * Redesigned type aliases in serialization library.
  58. * Fixed the code (removed CRef-s, added explicit
  59. * initializers etc.)
  60. *
  61. * Revision 1.45  2003/10/06 18:40:15  grichenk
  62. * Added e_MaxChoice enum
  63. *
  64. * Revision 1.44  2003/05/08 16:59:08  gouriano
  65. * added comment about the meaning of typedef for each class member
  66. *
  67. * Revision 1.43  2003/04/29 18:31:09  gouriano
  68. * object data member initialization verification
  69. *
  70. * Revision 1.42  2003/03/11 20:06:47  kuznets
  71. * iterate -> ITERATE
  72. *
  73. * Revision 1.41  2003/03/11 17:59:16  gouriano
  74. * reimplement CInvalidChoiceSelection exception
  75. *
  76. * Revision 1.40  2003/03/10 21:21:10  gouriano
  77. * use CSerialException in generated code
  78. *
  79. * Revision 1.39  2003/03/10 18:55:18  gouriano
  80. * use new structured exceptions (based on CException)
  81. *
  82. * Revision 1.38  2003/02/12 21:39:52  gouriano
  83. * corrected code generator so primitive data types (bool,int,etc)
  84. * are returned by value, not by reference
  85. *
  86. * Revision 1.37  2002/11/19 19:48:28  gouriano
  87. * added support of XML attributes of choice variants
  88. *
  89. * Revision 1.36  2002/11/18 19:48:46  grichenk
  90. * Removed "const" from datatool-generated setters
  91. *
  92. * Revision 1.35  2002/11/14 21:03:40  gouriano
  93. * added support of XML attribute lists
  94. *
  95. * Revision 1.34  2002/10/15 13:58:04  gouriano
  96. * use "noprefix" flag
  97. *
  98. * Revision 1.33  2002/08/14 17:14:25  grichenk
  99. * Fixed function name conflict on Win32: renamed
  100. * GetClassName() -> GetClassNameDT()
  101. *
  102. * Revision 1.32  2002/07/25 15:02:41  grichenk
  103. * Removed non-const GetXXX() method, use SetXXX() instead
  104. *
  105. * Revision 1.31  2002/05/15 20:22:04  grichenk
  106. * Added CSerialObject -- base class for all generated ASN.1 classes
  107. *
  108. * Revision 1.30  2002/01/16 18:56:34  grichenk
  109. * Removed CRef<> argument from choice variant setter, updated sources to
  110. * use references instead of CRef<>s
  111. *
  112. * Revision 1.29  2001/06/21 19:47:39  grichenk
  113. * Copy constructor and operator=() moved to "private" section
  114. *
  115. * Revision 1.28  2001/06/13 14:40:02  grichenk
  116. * Modified class and choice info generation code to avoid warnings
  117. *
  118. * Revision 1.27  2001/06/11 14:35:02  grichenk
  119. * Added support for numeric tags in ASN.1 specifications and data streams.
  120. *
  121. * Revision 1.26  2001/05/17 15:07:11  lavr
  122. * Typos corrected
  123. *
  124. * Revision 1.25  2000/11/29 17:42:42  vasilche
  125. * Added CComment class for storing/printing ASN.1/XML module comments.
  126. * Added srcutil.hpp file to reduce file dependency.
  127. *
  128. * Revision 1.24  2000/11/07 17:26:24  vasilche
  129. * Added module names to CTypeInfo and CEnumeratedTypeValues
  130. * Added possibility to set include directory for whole module
  131. *
  132. * Revision 1.23  2000/08/28 13:22:03  vasilche
  133. * Fixed reference to undefined kEmptyChoice.
  134. *
  135. * Revision 1.22  2000/08/25 15:59:20  vasilche
  136. * Renamed directory tool -> datatool.
  137. *
  138. * Revision 1.21  2000/07/11 20:36:28  vasilche
  139. * Removed unnecessary generation of namespace references for enum members.
  140. * Removed obsolete methods.
  141. *
  142. * Revision 1.20  2000/07/03 18:42:57  vasilche
  143. * Added interface to typeinfo via CObjectInfo and CConstObjectInfo.
  144. *
  145. * Revision 1.19  2000/06/27 16:34:48  vasilche
  146. * Fixed generated comments.
  147. * Fixed class names conflict. Now internal classes' names begin with "C_".
  148. *
  149. * Revision 1.18  2000/06/16 16:31:37  vasilche
  150. * Changed implementation of choices and classes info to allow use of the same classes in generated and user written classes.
  151. *
  152. * Revision 1.17  2000/05/03 14:38:17  vasilche
  153. * SERIAL: added support for delayed reading to generated classes.
  154. * DATATOOL: added code generation for delayed reading.
  155. *
  156. * Revision 1.16  2000/04/17 19:11:07  vasilche
  157. * Fixed failed assertion.
  158. * Removed redundant namespace specifications.
  159. *
  160. * Revision 1.15  2000/04/12 15:36:48  vasilche
  161. * Added -on <namespace> argument to datatool.
  162. * Removed unnecessary namespace specifications in generated files.
  163. *
  164. * Revision 1.14  2000/04/07 19:26:23  vasilche
  165. * Added namespace support to datatool.
  166. * By default with argument -oR datatool will generate objects in namespace
  167. * NCBI_NS_NCBI::objects (aka ncbi::objects).
  168. * Datatool's classes also moved to NCBI namespace.
  169. *
  170. * Revision 1.13  2000/04/06 16:11:25  vasilche
  171. * Removed unneeded calls to Reset().
  172. *
  173. * Revision 1.12  2000/04/03 18:47:29  vasilche
  174. * Added main include file for generated headers.
  175. * serialimpl.hpp is included in generated sources with GetTypeInfo methods
  176. *
  177. * Revision 1.11  2000/03/29 15:52:25  vasilche
  178. * Generated files names limited to 31 symbols due to limitations of Mac.
  179. * Removed unions with only one member.
  180. *
  181. * Revision 1.10  2000/03/17 16:49:54  vasilche
  182. * Added copyright message to generated files.
  183. * All objects pointers in choices now share the only CObject pointer.
  184. * All setters/getters made public until we'll find better solution.
  185. *
  186. * Revision 1.9  2000/03/08 14:40:00  vasilche
  187. * Renamed NewInstance() -> New().
  188. *
  189. * Revision 1.8  2000/03/07 20:04:59  vasilche
  190. * Added NewInstance method to generated classes.
  191. *
  192. * Revision 1.7  2000/03/07 14:06:30  vasilche
  193. * Added generation of reference counted objects.
  194. *
  195. * Revision 1.6  2000/02/17 20:05:06  vasilche
  196. * Inline methods now will be generated in *_Base.inl files.
  197. * Fixed processing of StringStore.
  198. * Renamed in choices: Selected() -> Which(), E_choice -> E_Choice.
  199. * Enumerated values now will preserve case as in ASN.1 definition.
  200. *
  201. * Revision 1.5  2000/02/11 17:09:30  vasilche
  202. * Removed unneeded flags.
  203. *
  204. * Revision 1.4  2000/02/03 21:58:30  vasilche
  205. * Fixed tipo leading to memory leak in generated files.
  206. *
  207. * Revision 1.3  2000/02/03 20:16:15  vasilche
  208. * Fixed bug in type info generation for templates.
  209. *
  210. * Revision 1.2  2000/02/02 14:57:06  vasilche
  211. * Added missing NCBI_NS_NCBI and NCBI_NS_STD macros to generated code.
  212. *
  213. * Revision 1.1  2000/02/01 21:47:54  vasilche
  214. * Added CGeneratedChoiceTypeInfo for generated choice classes.
  215. * Removed CMemberInfo subclasses.
  216. * Added support for DEFAULT/OPTIONAL members.
  217. * Changed class generation.
  218. * Moved datatool headers to include/internal/serial/tool.
  219. *
  220. * Revision 1.8  2000/01/10 19:46:47  vasilche
  221. * Fixed encoding/decoding of REAL type.
  222. * Fixed encoding/decoding of StringStore.
  223. * Fixed encoding/decoding of NULL type.
  224. * Fixed error reporting.
  225. * Reduced object map (only classes).
  226. *
  227. * Revision 1.7  1999/12/28 18:56:00  vasilche
  228. * Reduced size of compiled object files:
  229. * 1. avoid inline or implicit virtual methods (especially destructors).
  230. * 2. avoid std::string's methods usage in inline methods.
  231. * 3. avoid string literals ("xxx") in inline methods.
  232. *
  233. * Revision 1.6  1999/12/17 19:05:19  vasilche
  234. * Simplified generation of GetTypeInfo methods.
  235. *
  236. * Revision 1.5  1999/12/01 17:36:28  vasilche
  237. * Fixed CHOICE processing.
  238. *
  239. * Revision 1.4  1999/11/18 17:13:07  vasilche
  240. * Fixed generation of ENUMERATED CHOICE and VisibleString.
  241. * Added generation of initializers to zero for primitive types and pointers.
  242. *
  243. * Revision 1.3  1999/11/16 15:41:17  vasilche
  244. * Added plain pointer choice.
  245. * By default we use C pointer instead of auto_ptr.
  246. * Start adding initializers.
  247. *
  248. * Revision 1.2  1999/11/15 19:36:20  vasilche
  249. * Fixed warnings on GCC
  250. *
  251. * ===========================================================================
  252. */
  253. #include <ncbi_pch.hpp>
  254. #include <corelib/ncbiutil.hpp>
  255. #include <serial/datatool/exceptions.hpp>
  256. #include <serial/datatool/type.hpp>
  257. #include <serial/datatool/choicestr.hpp>
  258. #include <serial/datatool/stdstr.hpp>
  259. #include <serial/datatool/code.hpp>
  260. #include <serial/datatool/srcutil.hpp>
  261. #include <serial/serialdef.hpp>
  262. BEGIN_NCBI_SCOPE
  263. #define STATE_ENUM "E_Choice"
  264. #define STATE_MEMBER "m_choice"
  265. #define STRING_TYPE_FULL "NCBI_NS_STD::string"
  266. #define STRING_TYPE "string"
  267. #define STRING_MEMBER "m_string"
  268. #define OBJECT_TYPE_FULL "NCBI_NS_NCBI::CSerialObject"
  269. #define OBJECT_TYPE "CSerialObject"
  270. #define OBJECT_MEMBER "m_object"
  271. #define STATE_PREFIX "e_"
  272. #define STATE_NOT_SET "e_not_set"
  273. #define DELAY_MEMBER "m_delayBuffer"
  274. #define DELAY_TYPE_FULL "NCBI_NS_NCBI::CDelayBuffer"
  275. CChoiceTypeStrings::CChoiceTypeStrings(const string& externalName,
  276.                                        const string& className)
  277.     : CParent(externalName, className),
  278.       m_HaveAssignment(false)
  279. {
  280. }
  281. CChoiceTypeStrings::~CChoiceTypeStrings(void)
  282. {
  283. }
  284. void CChoiceTypeStrings::AddVariant(const string& name,
  285.                                     const AutoPtr<CTypeStrings>& type,
  286.                                     bool delayed, int tag,
  287.                                     bool noPrefix, bool attlist, bool noTag,
  288.                                     bool simple, const CDataType* dataType)
  289. {
  290.     m_Variants.push_back(SVariantInfo(name, type, delayed, tag,
  291.                                       noPrefix,attlist,noTag,simple,dataType));
  292. }
  293. CChoiceTypeStrings::SVariantInfo::SVariantInfo(const string& name,
  294.                                                const AutoPtr<CTypeStrings>& t,
  295.                                                bool del, int tag,
  296.                                                bool noPrefx, bool attlst,
  297.                                                bool noTg,bool simpl,
  298.                                                const CDataType* dataTp)
  299.     : externalName(name), cName(Identifier(name)),
  300.       type(t), delayed(del), memberTag(tag),
  301.       noPrefix(noPrefx), attlist(attlst), noTag(noTg), simple(simpl),
  302.       dataType(dataTp)
  303. {
  304.     switch ( type->GetKind() ) {
  305.     case eKindString:
  306.         memberType = eStringMember;
  307.         break;
  308.     case eKindStd:
  309.     case eKindEnum:
  310.         memberType = eSimpleMember;
  311.         break;
  312.     case eKindObject:
  313.         memberType = eObjectPointerMember;
  314.         break;
  315.     case eKindPointer:
  316.     case eKindRef:
  317.         ERR_POST("pointer as choice variant");
  318.         memberType = ePointerMember;
  319.         break;
  320.     default:
  321.         memberType = ePointerMember;
  322.         break;
  323.     }
  324. }
  325. bool CChoiceTypeStrings::x_IsNullType(TVariants::const_iterator i) const
  326. {
  327.     return (dynamic_cast<CNullTypeStrings*>(i->type.get()) != 0);
  328. }
  329. bool CChoiceTypeStrings::x_IsNullWithAttlist(TVariants::const_iterator i) const
  330. {
  331.     if (i->dataType) {
  332.         const CDataType* resolved = i->dataType->Resolve();
  333.         if (resolved && resolved != i->dataType) {
  334.             CClassTypeStrings* typeStr = resolved->GetTypeStr();
  335.             if (typeStr) {
  336.                 ITERATE ( TMembers, ir, typeStr->m_Members ) {
  337.                     if (ir->simple) {
  338.                         return CClassTypeStrings::x_IsNullType(ir);
  339.                     }
  340.                 }
  341.             }
  342.         }
  343.     }
  344.     return false;
  345. }
  346. void CChoiceTypeStrings::GenerateClassCode(CClassCode& code,
  347.                                            CNcbiOstream& setters,
  348.                                            const string& methodPrefix,
  349.                                            bool haveUserClass,
  350.                                            const string& classPrefix) const
  351. {
  352.     bool haveObjectPointer = false;
  353.     bool havePointers = false;
  354.     bool haveSimple = false;
  355.     bool haveString = false;
  356.     bool delayed = false;
  357.     bool haveAttlist = false;
  358.     string codeClassName = GetClassNameDT();
  359.     if ( haveUserClass )
  360.         codeClassName += "_Base";
  361.     // generate variants code
  362.     {
  363.         ITERATE ( TVariants, i, m_Variants ) {
  364.             switch ( i->memberType ) {
  365.             case ePointerMember:
  366.                 havePointers = true;
  367.                 i->type->GeneratePointerTypeCode(code);
  368.                 break;
  369.             case eObjectPointerMember:
  370.                 if (i->attlist) {
  371.                     haveAttlist = true;
  372.                 } else {
  373.                     haveObjectPointer = true;
  374.                 }
  375.                 i->type->GeneratePointerTypeCode(code);
  376.                 break;
  377.             case eSimpleMember:
  378.                 haveSimple = true;
  379.                 i->type->GenerateTypeCode(code);
  380.                 break;
  381.             case eStringMember:
  382.                 haveString = true;
  383.                 i->type->GenerateTypeCode(code);
  384.                 break;
  385.             }
  386.             if ( i->delayed )
  387.                 delayed = true;
  388.         }
  389.     }
  390.     if ( delayed )
  391.         code.HPPIncludes().insert("serial/delaybuf");
  392.     bool haveUnion = havePointers || haveSimple ||
  393.         (haveString && haveObjectPointer);
  394.     if ( haveString && haveUnion ) {
  395.         // convert string member to pointer member
  396.         havePointers = true;
  397.     }
  398.     string stdNamespace = 
  399.         code.GetNamespace().GetNamespaceRef(CNamespace::KSTDNamespace);
  400.     string ncbiNamespace =
  401.         code.GetNamespace().GetNamespaceRef(CNamespace::KNCBINamespace);
  402.     if ( HaveAssignment() ) {
  403.         code.ClassPublic() <<
  404.             "    /// Copy constructor.n"
  405.             "    "<<codeClassName<<"(const "<<codeClassName<<"& src);nn"
  406.             "   /// Assignment operatorn"
  407.             "    "<<codeClassName<<"& operator=(const "<<codeClassName<<"& src);nnn";
  408.     } else {
  409.         code.ClassPrivate() <<
  410.             "    // copy constructor and assignment operatorn"
  411.             "    "<<codeClassName<<"(const "<<codeClassName<<"& );n"
  412.             "    "<<codeClassName<<"& operator=(const "<<codeClassName<<"& );n";
  413.     }
  414.     // generated choice enum
  415.     {
  416.         string cName(STATE_NOT_SET);
  417.         size_t currlen, maxlen = cName.size() + 2;
  418.         ITERATE(TVariants, i, m_Variants) {
  419.             if (!i->attlist) {
  420.                 maxlen = max(maxlen,i->cName.size());
  421.             }
  422.         }
  423.         code.ClassPublic() <<
  424.             "n    /// Choice variants.n"
  425.             "    enum "STATE_ENUM" {n"
  426.             "        "STATE_NOT_SET" = "<<kEmptyChoice
  427.             <<"," ;
  428.         for (currlen = strlen(STATE_NOT_SET)+2; currlen < maxlen; ++currlen) {
  429.             code.ClassPublic() << " ";
  430.         }
  431.         code.ClassPublic()
  432.             <<"  ///< No variant selectedn" ;
  433.         TMemberIndex currIndex = kEmptyChoice;
  434.         bool needIni = false;
  435.         for (TVariants::const_iterator i= m_Variants.begin(); i != m_Variants.end();) {
  436.             ++currIndex;
  437.             if (!i->attlist) {
  438.                 cName = i->cName;
  439.                 code.ClassPublic() << "        "STATE_PREFIX<<cName;
  440.                 if (needIni) {
  441.                     code.ClassPublic() << " = "<<currIndex;
  442.                     needIni = false;
  443.                 }
  444.                 ++i;
  445.                 if (i != m_Variants.end()) {
  446.                     code.ClassPublic() << ",";
  447.                 } else {
  448.                     code.ClassPublic() << " ";
  449.                 }
  450.                 for (currlen = cName.size(); currlen < maxlen; ++currlen) {
  451.                     code.ClassPublic() << " ";
  452.                 }
  453.                 code.ClassPublic() << "  ///< Variant "<<cName<<" is selected.";
  454.                 code.ClassPublic() << "n";
  455.             } else {
  456.                 ++i;
  457.                 needIni = true;
  458.             }
  459.         }
  460.         code.ClassPublic() << "    };n";
  461.         code.ClassPublic() << "    /// Maximum+1 value of the choice variant enumerator.n";
  462.         code.ClassPublic() <<
  463.             "    enum E_ChoiceStopper {n"
  464.             "        e_MaxChoice = " << currIndex+1 << " ///< == "STATE_PREFIX
  465.                 << m_Variants.rbegin()->cName << "+1n"
  466.             "    };n"
  467.             "n";
  468.     }
  469.     code.ClassPublic() <<
  470.         "    /// Reset the selection (set it to "STATE_NOT_SET").n"
  471.         "    ";
  472.     if ( HaveUserClass() )
  473.         code.ClassPublic() << "virtual ";
  474.     code.ClassPublic() <<
  475.         "void Reset(void);n"
  476.         "n";
  477.     // generate choice methods
  478.     code.ClassPublic() <<
  479.         "    /// Which variant is currently selected.n";
  480.     if (CClassCode::GetDoxygenComments()) {
  481.         code.ClassPublic() <<
  482.             "    ///n"
  483.             "    /// @returnn"
  484.             "    ///   Choice state enumerator.n";
  485.     }
  486.     code.ClassPublic() <<
  487.         "    "STATE_ENUM" Which(void) const;nn"
  488.         "    /// Verify selection, throw exception if it differs from the expected.n";
  489.     if (CClassCode::GetDoxygenComments()) {
  490.         code.ClassPublic() <<
  491.             "    ///n"
  492.             "    /// @param indexn"
  493.             "    ///   Expected selection.n";
  494.     }
  495.     code.ClassPublic() <<
  496.         "    void CheckSelected("STATE_ENUM" index) const;nn"
  497.         "    /// Throw 'InvalidSelection' exception.n";
  498.     if (CClassCode::GetDoxygenComments()) {
  499.         code.ClassPublic() <<
  500.             "    ///n"
  501.             "    /// @param indexn"
  502.             "    ///   Expected selection.n";
  503.     }
  504.     code.ClassPublic() <<
  505.         "    void ThrowInvalidSelection("STATE_ENUM" index) const;nn"
  506.         "    /// Retrieve selection name (for diagnostic purposes).n";
  507.     if (CClassCode::GetDoxygenComments()) {
  508.         code.ClassPublic() <<
  509.             "    ///n"
  510.             "    /// @param indexn"
  511.             "    ///   One of possible selection states.n"
  512.             "    /// @returnn"
  513.             "    ///   Name string.n";
  514.     }
  515.     code.ClassPublic() <<
  516.         "    static "<<stdNamespace<<"string SelectionName("STATE_ENUM" index);n"
  517.         "n";
  518.     setters <<
  519.         "    /// Select the requested variant if needed.n";
  520.     if (CClassCode::GetDoxygenComments()) {
  521.         setters <<
  522.             "    ///n"
  523.             "    /// @param indexn"
  524.             "    ///   New selection state.n"
  525.             "    /// @param resetn"
  526.             "    ///   Flag that defines the resetting of the variant data. The data willn"
  527.             "    ///   be reset if either the current selection differs from the new one,n"
  528.             "    ///   or the flag is set to eDoResetVariant.n";
  529.     }
  530.     setters <<
  531.         "    void Select("STATE_ENUM" index, "<<ncbiNamespace<<"EResetVariant reset = "<<ncbiNamespace<<"eDoResetVariant);n";
  532.     if ( delayed ) {
  533.         setters <<
  534.             "    /// Select the requested variant using delay buffer (for internal use).n";
  535.         if (CClassCode::GetDoxygenComments()) {
  536.             setters <<
  537.                 "    ///n"
  538.                 "    /// @param indexn"
  539.                 "    ///   New selection state.n";
  540.         }
  541.         setters <<
  542.             "    void SelectDelayBuffer("STATE_ENUM" index);n";
  543.     }
  544.     setters <<
  545.         "n";
  546.     CNcbiOstream& methods = code.Methods();
  547.     CNcbiOstream& inlineMethods = code.InlineMethods();
  548.     inlineMethods <<
  549.         "inlinen"<<
  550.         methodPrefix<<STATE_ENUM" "<<methodPrefix<<"Which(void) constn"
  551.         "{n"
  552.         "    return "STATE_MEMBER";n"
  553.         "}n"
  554.         "n"
  555.         "inlinen"
  556.         "void "<<methodPrefix<<"CheckSelected("STATE_ENUM" index) constn"
  557.         "{n"
  558.         "    if ( "STATE_MEMBER" != index )n"
  559.         "        ThrowInvalidSelection(index);n"
  560.         "}n"
  561.         "n"
  562.         "inlinen"
  563.         "void "<<methodPrefix<<"Select("STATE_ENUM" index, NCBI_NS_NCBI::EResetVariant reset)n"
  564.         "{n"
  565.         "    if ( reset == NCBI_NS_NCBI::eDoResetVariant || "STATE_MEMBER" != index ) {n"
  566.         "        if ( "STATE_MEMBER" != "STATE_NOT_SET" )n"
  567.         "            Reset();n"
  568.         "        DoSelect(index);n"
  569.         "    }n"
  570.         "}n"
  571.         "n";
  572.     if ( delayed ) {
  573.         inlineMethods <<
  574.             "inlinen"
  575.             "void "<<methodPrefix<<"SelectDelayBuffer("STATE_ENUM" index)n"
  576.             "{n"
  577.             "    if ( "STATE_MEMBER" != "STATE_NOT_SET" || "DELAY_MEMBER".GetIndex() != (index - 1))n"
  578.             "        NCBI_THROW(ncbi::CSerialException,eIllegalCall, "illegal call");n"
  579.             "    "STATE_MEMBER" = index;n"
  580.             "}n"
  581.             "n";
  582.     }
  583.     if ( HaveAssignment() ) {
  584.         inlineMethods <<
  585.             "inlinen"<<
  586.             methodPrefix<<codeClassName<<"(const "<<codeClassName<<"& src)n"
  587.             "{n"
  588.             "    DoAssign(src);n"
  589.             "}n"
  590.             "n"
  591.             "inlinen"<<
  592.             methodPrefix<<codeClassName<<"& "<<methodPrefix<<"operator=(const "<<codeClassName<<"& src)n"
  593.             "{n"
  594.             "    if ( this != &src ) {n"
  595.             "        Reset();n"
  596.             "        DoAssign(src);n"
  597.             "    }n"
  598.             "    return *this;n"
  599.             "}n"
  600.             "n";
  601.     }
  602.     // generate choice state
  603.     code.ClassPrivate() <<
  604.         "    // choice staten"
  605.         "    "STATE_ENUM" "STATE_MEMBER";n"
  606.         "    // helper methodsn"
  607.         "    void DoSelect("STATE_ENUM" index);n";
  608.     if ( HaveAssignment() ) {
  609.         code.ClassPrivate() <<
  610.             "    void DoAssign(const "<<codeClassName<<"& src);n";
  611.     }
  612.     code.ClassPrivate() <<
  613.         "n";
  614.     // generate initialization code
  615.     code.AddInitializer(STATE_MEMBER, STATE_NOT_SET);
  616.     if (haveAttlist) {
  617.         ITERATE ( TVariants, i, m_Variants ) {
  618.             if (i->attlist) {
  619.                 string member("m_");
  620.                 member += i->cName;
  621.                 string init("new C_");
  622.                 init += i->cName;
  623.                 init += "()";
  624.                 code.AddInitializer(member, init);
  625.             }
  626.         }
  627.     }
  628.     // generate destruction code
  629.     code.AddDestructionCode("if ( "STATE_MEMBER" != "STATE_NOT_SET" )n"
  630.                             "    Reset();");
  631.     // generate Reset method
  632.     {
  633.         methods <<
  634.             "void "<<methodPrefix<<"Reset(void)n"
  635.             "{n";
  636.         if (haveAttlist) {
  637.             ITERATE ( TVariants, i, m_Variants ) {
  638.                 if (i->attlist) {
  639.                     methods <<
  640.                         "    Reset" << i->cName << "();n";
  641.                 }
  642.             }
  643.         }
  644.         if ( haveObjectPointer || havePointers || haveString ) {
  645.             if ( delayed ) {
  646.                 methods <<
  647.                     "    if ( "DELAY_MEMBER" )n"
  648.                     "        "DELAY_MEMBER".Forget();n"
  649.                     "    elsen";
  650.             }
  651.             methods <<
  652.                 "    switch ( "STATE_MEMBER" ) {n";
  653.             // generate destruction code for pointers
  654.             ITERATE ( TVariants, i, m_Variants ) {
  655.                 if (i->attlist) {
  656.                     continue;
  657.                 }
  658.                 if ( i->memberType == ePointerMember ) {
  659.                     methods <<
  660.                         "    case "STATE_PREFIX<<i->cName<<":n";
  661.                     WriteTabbed(methods, 
  662.                                 i->type->GetDestructionCode("*m_"+i->cName),
  663.                                 "        ");
  664.                     methods <<
  665.                         "        delete m_"<<i->cName<<";n"
  666.                         "        break;n";
  667.                 }
  668.             }
  669.             if ( haveString ) {
  670.                 // generate destruction code for string
  671.                 ITERATE ( TVariants, i, m_Variants ) {
  672.                     if (i->attlist) {
  673.                         continue;
  674.                     }
  675.                     if ( i->memberType == eStringMember ) {
  676.                         methods <<
  677.                             "    case "STATE_PREFIX<<i->cName<<":n";
  678.                     }
  679.                 }
  680.                 if ( haveUnion ) {
  681.                     // string is pointer inside union
  682.                     methods <<
  683.                         "        delete "STRING_MEMBER";n";
  684.                 }
  685.                 else {
  686.                     methods <<
  687.                         "        "STRING_MEMBER".erase();n";
  688.                 }
  689.                 methods <<
  690.                     "        break;n";
  691.             }
  692.             if ( haveObjectPointer ) {
  693.                 // generate destruction code for pointers to CObject
  694.                 ITERATE ( TVariants, i, m_Variants ) {
  695.                     if (i->attlist) {
  696.                         continue;
  697.                     }
  698.                     if ( i->memberType == eObjectPointerMember ) {
  699.                         methods <<
  700.                             "    case "STATE_PREFIX<<i->cName<<":n";
  701.                     }
  702.                 }
  703.                 methods <<
  704.                     "        "OBJECT_MEMBER"->RemoveReference();n"
  705.                     "        break;n";
  706.             }
  707.             methods <<
  708.                 "    default:n"
  709.                 "        break;n"
  710.                 "    }n";
  711.         }
  712.         methods <<
  713.             "    "STATE_MEMBER" = "STATE_NOT_SET";n"
  714.             "}n"
  715.             "n";
  716.     }
  717.     // generate Assign method
  718.     if ( HaveAssignment() ) {
  719.         methods <<
  720.             "void "<<methodPrefix<<"DoAssign(const "<<codeClassName<<"& src)n"
  721.             "{n"
  722.             "    "STATE_ENUM" index = src.Which();n"
  723.             "    switch ( index ) {n";
  724.         ITERATE ( TVariants, i, m_Variants ) {
  725.             switch ( i->memberType ) {
  726.             case eSimpleMember:
  727.                 methods <<
  728.                     "    case "STATE_PREFIX<<i->cName<<":n"
  729.                     "        m_"<<i->cName<<" = src.m_"<<i->cName<<";n"
  730.                     "        break;n";
  731.                 break;
  732.             case ePointerMember:
  733.                 methods <<
  734.                     "    case "STATE_PREFIX<<i->cName<<":n"
  735.                     "        m_"<<i->cName<<" = new T"<<i->cName<<"(*src.m_"<<i->cName<<");n"
  736.                     "        break;n";
  737.                 break;
  738.             case eStringMember:
  739.                 _ASSERT(haveString);
  740.                 // will be handled specially
  741.                 break;
  742.             case eObjectPointerMember:
  743.                 // will be handled specially
  744.                 _ASSERT(haveObjectPointer);
  745.                 break;
  746.             }
  747.         }
  748.         if ( haveString ) {
  749.             // generate copy code for string
  750.             ITERATE ( TVariants, i, m_Variants ) {
  751.                 if ( i->memberType == eStringMember ) {
  752.                     methods <<
  753.                         "    case "STATE_PREFIX<<i->cName<<":n";
  754.                 }
  755.             }
  756.             if ( haveUnion ) {
  757.                 // string is pointer
  758.                 methods <<
  759.                     "        "STRING_MEMBER" = src."STRING_MEMBER";n";
  760.             }
  761.             else {
  762.                 methods <<
  763.                     "        "STRING_MEMBER" = new "STRING_TYPE_FULL"(*src."STRING_MEMBER");n";
  764.             }
  765.             methods <<
  766.                 "        break;n";
  767.         }
  768.         if ( haveObjectPointer ) {
  769.             // generate copy code for string
  770.             ITERATE ( TVariants, i, m_Variants ) {
  771.                 if ( i->memberType == eObjectPointerMember ) {
  772.                     methods <<
  773.                         "    case "STATE_PREFIX<<i->cName<<":n";
  774.                 }
  775.             }
  776.             methods <<
  777.                 "        ("OBJECT_MEMBER" = src."OBJECT_MEMBER")->AddReference();n"
  778.                 "        break;n";
  779.         }
  780.         methods <<
  781.             "    default:n"
  782.             "        break;n"
  783.             "    }n"
  784.             "    "STATE_MEMBER" = index;n"
  785.             "}n"
  786.             "n";
  787.     }
  788.     // generate Select method
  789.     {
  790.         methods <<
  791.             "void "<<methodPrefix<<"DoSelect("STATE_ENUM" index)n"
  792.             "{n";
  793.         if ( haveUnion || haveObjectPointer ) {
  794.             methods <<
  795.                 "    switch ( index ) {n";
  796.             ITERATE ( TVariants, i, m_Variants ) {
  797.                 if (i->attlist) {
  798.                     continue;
  799.                 }
  800.                 switch ( i->memberType ) {
  801.                 case eSimpleMember:
  802.                     if (!x_IsNullType(i)) {
  803.                         string init = i->type->GetInitializer();
  804.                         methods <<
  805.                             "    case "STATE_PREFIX<<i->cName<<":n"
  806.                             "        m_"<<i->cName<<" = "<<init<<";n"
  807.                             "        break;n";
  808.                     }
  809.                     break;
  810.                 case ePointerMember:
  811.                     methods <<
  812.                         "    case "STATE_PREFIX<<i->cName<<":n"
  813.                         "        m_"<<i->cName<<" = "<<i->type->NewInstance(NcbiEmptyString)<<";n"
  814.                         "        break;n";
  815.                     break;
  816.                 case eObjectPointerMember:
  817.                     methods <<
  818.                         "    case "STATE_PREFIX<<i->cName<<":n"
  819.                         "        ("OBJECT_MEMBER" = "<<i->type->NewInstance(NcbiEmptyString)<<")->AddReference();n"
  820.                         "        break;n";
  821.                     break;
  822.                 case eStringMember:
  823.                     // will be handled specially
  824.                     break;
  825.                 }
  826.             }
  827.             if ( haveString ) {
  828.                 ITERATE ( TVariants, i, m_Variants ) {
  829.                     if ( i->memberType == eStringMember ) {
  830.                         methods <<
  831.                             "    case "STATE_PREFIX<<i->cName<<":n";
  832.                     }
  833.                 }
  834.                 methods <<
  835.                     "        "STRING_MEMBER" = new "STRING_TYPE_FULL";n"
  836.                     "        break;n";
  837.             }
  838.             methods <<
  839.                 "    default:n"
  840.                 "        break;n"
  841.                 "    }n";
  842.         }
  843.         methods <<
  844.             "    "STATE_MEMBER" = index;n"
  845.             "}n"
  846.             "n";
  847.     }
  848.     // generate choice variants names
  849.     code.ClassPrivate() <<
  850.         "    static const char* const sm_SelectionNames[];n";
  851.     {
  852.         methods <<
  853.             "const char* const "<<methodPrefix<<"sm_SelectionNames[] = {n"
  854.             "    "not set"";
  855.         ITERATE ( TVariants, i, m_Variants ) {
  856.             methods << ",n"
  857.                 "    ""<<i->externalName<<""";
  858.             if (i->attlist) {
  859.                 methods << " /* place holder */";
  860.             }
  861.         }
  862.         methods << "n"
  863.             "};n"
  864.             "n"
  865.             "NCBI_NS_STD::string "<<methodPrefix<<"SelectionName("STATE_ENUM" index)n"
  866.             "{n"
  867.             "    return NCBI_NS_NCBI::CInvalidChoiceSelection::GetName(index, sm_SelectionNames, sizeof(sm_SelectionNames)/sizeof(sm_SelectionNames[0]));n"
  868.             "}n"
  869.             "n"
  870.             "void "<<methodPrefix<<"ThrowInvalidSelection("STATE_ENUM" index) constn"
  871.             "{n"
  872.             "    throw NCBI_NS_NCBI::CInvalidChoiceSelection(__FILE__,__LINE__,m_choice, index, sm_SelectionNames, sizeof(sm_SelectionNames)/sizeof(sm_SelectionNames[0]));n"
  873.             "}n"
  874.             "n";
  875.     }
  876.     
  877.     // generate variant types
  878.     {
  879.         code.ClassPublic() <<
  880.             "    // typesn";
  881.         ITERATE ( TVariants, i, m_Variants ) {
  882.             string cType = i->type->GetCType(code.GetNamespace());
  883.             if (!x_IsNullType(i)) {
  884.                 code.ClassPublic() <<
  885.                     "    typedef "<<cType<<" T"<<i->cName<<";n";
  886.             }
  887.         }
  888.         code.ClassPublic() << 
  889.             "n";
  890.     }
  891.     // generate variant getters & setters
  892.     {
  893.         code.ClassPublic() <<
  894.             "    // gettersn";
  895.         setters <<
  896.             "    // settersnn";
  897.         ITERATE ( TVariants, i, m_Variants ) {
  898.             string cType = i->type->GetCType(code.GetNamespace());
  899.             string tType = "T" + i->cName;
  900.             string rType = i->type->GetPrefixedCType(code.GetNamespace(),methodPrefix);
  901.             bool isNull = x_IsNullType(i);
  902.             bool isNullWithAtt = x_IsNullWithAttlist(i);
  903.             if (!CClassCode::GetDoxygenComments()) {
  904.                 if (!isNull) {
  905.                     code.ClassPublic()
  906.                         << "    // typedef "<< cType <<" "<<tType<<"n";
  907.                 } else {
  908.                     code.ClassPublic() << "n";
  909.                 }
  910.             }
  911.             if (i->attlist) {
  912.                 if (CClassCode::GetDoxygenComments()) {
  913.                     code.ClassPublic() <<
  914.                         "    /// Reset the attribute list.n";
  915.                 }
  916.                 code.ClassPublic() <<
  917.                     "    void Reset"<<i->cName<<"(void);n";
  918.             } else {
  919.                 if (CClassCode::GetDoxygenComments()) {
  920.                     code.ClassPublic() <<
  921.                         "n"
  922.                         "    /// Check if variant "<<i->cName<<" is selected.n"
  923.                         "    ///n";
  924.                     if (!isNull) {
  925.                         code.ClassPublic()
  926.                             << "    /// "<<i->cName<<" type is defined as 'typedef "<< cType <<" "<<tType<<"'.n";
  927.                     }
  928.                     code.ClassPublic() <<
  929.                         "    /// @returnn"
  930.                         "    ///   - true, if the variant is selected.n"
  931.                         "    ///   - false, otherwise.n";
  932.                 }
  933.                 code.ClassPublic() <<
  934.                     "    bool Is"<<i->cName<<"(void) const;n";
  935.             }
  936.             if (i->dataType && i->dataType->IsPrimitive()) {
  937.                 if (CClassCode::GetDoxygenComments()) {
  938.                     code.ClassPublic() <<
  939.                         "n"
  940.                         "    /// Get the variant data.n"
  941.                         "    ///n"
  942.                         "    /// @returnn"
  943.                         "    ///   Copy of the variant data.n";
  944.                 }
  945.                 code.ClassPublic() <<
  946.                     "    "<<tType<<" Get"<<i->cName<<"(void) const;n"
  947.                     "n";
  948.             } else {
  949.                 if (!isNull) {
  950.                     if (CClassCode::GetDoxygenComments()) {
  951.                         if (i->attlist) {
  952.                             code.ClassPublic() <<
  953.                                 "n"
  954.                                 "    /// Get the attribute list data.n";
  955.                         } else {
  956.                             code.ClassPublic() <<
  957.                                 "n"
  958.                                 "    /// Get the variant data.n";
  959.                         }
  960.                         code.ClassPublic() <<
  961.                             "    ///n"
  962.                             "    /// @returnn"
  963.                             "    ///   Reference to the data.n";
  964.                     }
  965.                     code.ClassPublic() <<
  966.                         "    const "<<tType<<"& Get"<<i->cName<<"(void) const;n";
  967.                 }
  968.             }
  969.             if (isNull) {
  970.                 if (CClassCode::GetDoxygenComments()) {
  971.                     setters <<
  972.                         "n"
  973.                         "    /// Select the variant.n";
  974.                 }
  975.                 setters <<
  976.                     "    void Set"<<i->cName<<"(void);n";
  977.             } else {
  978.                 if (CClassCode::GetDoxygenComments()) {
  979.                     if (i->attlist) {
  980.                         setters <<
  981.                             "n"
  982.                             "    /// Set the attribute list data.n"
  983.                             "    ///n"
  984.                             "    /// @returnn"
  985.                             "    ///   Reference to the data.n";
  986.                     } else {
  987.                         setters <<
  988.                             "n"
  989.                             "    /// Select the variant.n"
  990.                             "    ///n"
  991.                             "    /// @returnn"
  992.                             "    ///   Reference to the variant data.n";
  993.                     }
  994.                 }
  995.                 setters <<
  996.                     "    "<<tType<<"& Set"<<i->cName<<"(void);n";
  997.             }
  998.             if ( i->type->CanBeCopied() ) {
  999.                 if (i->attlist) {
  1000.                     if (CClassCode::GetDoxygenComments()) {
  1001.                         setters <<
  1002.                             "n"
  1003.                             "    /// Set the attribute list data.n"
  1004.                             "    ///n"
  1005.                             "    /// @param valuen"
  1006.                             "    ///   Reference to data.n";
  1007.                     }
  1008.                     setters <<
  1009.                         "    void Set"<<i->cName<<"("<<tType<<"& value);n";
  1010.                 } else {
  1011.                     if (!isNull) {
  1012.                         if (CClassCode::GetDoxygenComments()) {
  1013.                             setters <<
  1014.                                 "n"
  1015.                                 "    /// Select the variant and set its data.n"
  1016.                                 "    ///n"
  1017.                                 "    /// @param valuen"
  1018.                                 "    ///   Reference to variant data.n";
  1019.                         }
  1020.                         setters <<
  1021.                             "    void Set"<<i->cName<<"(const "<<tType<<"& value);n";
  1022.                     }
  1023.                 }
  1024.             }
  1025.             if ( i->memberType == eObjectPointerMember && !isNullWithAtt) {
  1026.                 if (CClassCode::GetDoxygenComments()) {
  1027.                     if (i->attlist) {
  1028.                         setters <<
  1029.                             "n"
  1030.                             "    /// Set the attribute list data.n";
  1031.                     } else {
  1032.                         setters <<
  1033.                             "    /// Select the variant and set its data.n";
  1034.                     }
  1035.                     setters <<
  1036.                         "    ///n"
  1037.                         "    /// @param valuen"
  1038.                         "    ///   Reference to the data.n";
  1039.                 }
  1040.                 setters <<
  1041.                     "    void Set"<<i->cName<<"("<<tType<<"& value);n";
  1042.             }
  1043.             string memberRef;
  1044.             string constMemberRef;
  1045.             bool inl = true;
  1046.             switch ( i->memberType ) {
  1047.             case eSimpleMember:
  1048.                 memberRef = constMemberRef = "m_"+i->cName;
  1049.                 break;
  1050.             case ePointerMember:
  1051.                 memberRef = constMemberRef = "*m_"+i->cName;
  1052.                 break;
  1053.             case eStringMember:
  1054.                 memberRef = STRING_MEMBER;
  1055.                 if ( haveUnion ) {
  1056.                     // string is pointer
  1057.                     memberRef = '*'+memberRef;
  1058.                 }
  1059.                 constMemberRef = memberRef;
  1060.                 break;
  1061.             case eObjectPointerMember:
  1062.                 memberRef = "*static_cast<T"+i->cName+"*>("OBJECT_MEMBER")";
  1063.                 constMemberRef = "*static_cast<const T"+i->cName+"*>("OBJECT_MEMBER")";
  1064.                 inl = false;
  1065.                 break;
  1066.             }
  1067.             if ( i->delayed )
  1068.                 inl = false;
  1069.             if (i->attlist) {
  1070.                 code.MethodStart(inl) <<
  1071.                     "void "<<methodPrefix<<"Reset"<<i->cName<<"(void)n"
  1072.                     "{n"
  1073.                     "    (*m_" <<i->cName<< ").Reset();n"
  1074.                     "}n"
  1075.                     "n";
  1076.                 if (i->dataType && i->dataType->IsPrimitive()) {
  1077.                     code.MethodStart(inl) << rType;
  1078.                 } else {
  1079.                     code.MethodStart(inl) << "const "<<rType<<"&";
  1080.                 }
  1081.                 code.Methods(inl) <<
  1082.                     " "<<methodPrefix<<"Get"<<i->cName<<"(void) constn"
  1083.                     "{n";
  1084.                 code.Methods(inl) <<
  1085.                     "    return (*m_"<<i->cName<<");n"
  1086.                     "}n"
  1087.                     "n";
  1088.                 code.MethodStart(inl) <<
  1089.                     rType<<"& "<<methodPrefix<<"Set"<<i->cName<<"(void)n"
  1090.                     "{n";
  1091.                 code.Methods(inl) <<
  1092.                     "    return (*m_"<<i->cName<<");n"
  1093.                     "}n"
  1094.                     "n";
  1095.                 code.MethodStart(inl) <<
  1096.                     "void "<<methodPrefix<<"Set"<<i->cName<<"("<<rType<<"& value)n"
  1097.                     "{n";
  1098.                 code.Methods(inl) <<
  1099.                     "    m_"<<i->cName<<".Reset(&value);n"
  1100.                     "}n"
  1101.                     "n";
  1102.             } else {
  1103.                 inlineMethods <<
  1104.                     "inlinen"
  1105.                     "bool "<<methodPrefix<<"Is"<<i->cName<<"(void) constn"
  1106.                     "{n"
  1107.                     "    return "STATE_MEMBER" == "STATE_PREFIX<<i->cName<<";n"
  1108.                     "}n"
  1109.                     "n";
  1110.                 if (i->dataType && i->dataType->IsPrimitive()) {
  1111.                     code.MethodStart(inl) << rType;
  1112.                 } else if (!isNull) {
  1113.                     code.MethodStart(inl) << "const "<<rType<<"&";
  1114.                 }
  1115.                 if (!isNull) {
  1116.                     code.Methods(inl) <<
  1117.                         " "<<methodPrefix<<"Get"<<i->cName<<"(void) constn"
  1118.                         "{n"
  1119.                         "    CheckSelected("STATE_PREFIX<<i->cName<<");n";
  1120.                     if ( i->delayed ) {
  1121.                         code.Methods(inl) <<
  1122.                             "    "DELAY_MEMBER".Update();n";
  1123.                     }
  1124.                     code.Methods(inl) <<
  1125.                         "    return "<<constMemberRef<<";n"
  1126.                         "}n"
  1127.                         "n";
  1128.                 }
  1129.                 if (isNull) {
  1130.                     code.MethodStart(inl) <<
  1131.                         "void "<<methodPrefix<<"Set"<<i->cName<<"(void)n";
  1132.                 } else {
  1133.                     code.MethodStart(inl) <<
  1134.                         rType<<"& "<<methodPrefix<<"Set"<<i->cName<<"(void)n";
  1135.                 }
  1136.                 code.Methods(inl) <<
  1137.                     "{n"
  1138.                     "    Select("STATE_PREFIX<<i->cName<<", NCBI_NS_NCBI::eDoNotResetVariant);n";
  1139.                 if (!isNull) {
  1140.                     if ( i->delayed ) {
  1141.                         code.Methods(inl) <<
  1142.                             "    "DELAY_MEMBER".Update();n";
  1143.                     }
  1144.                     if (isNullWithAtt) {
  1145.                         code.Methods(inl) <<
  1146.                             "    "<<rType<<"& value = "<<memberRef<<";n" <<
  1147.                             "    value.Set"<<i->cName<<"();n" <<
  1148.                             "    return value;n";
  1149.                     } else {
  1150.                         code.Methods(inl) <<
  1151.                             "    return "<<memberRef<<";n";
  1152.                     }
  1153.                 }
  1154.                 code.Methods(inl) <<
  1155.                     "}n"
  1156.                     "n";
  1157.                 if ( i->type->CanBeCopied() ) {
  1158.                     bool set_inl = i->dataType && i->dataType->IsPrimitive();
  1159.                     if (!isNull) {
  1160.                         code.MethodStart(set_inl) <<
  1161.                             "void "<<methodPrefix<<"Set"<<i->cName<<"("
  1162.                             "const " << rType << "&" << " value)n"
  1163.                             "{n"
  1164.                             "    Select("STATE_PREFIX<<i->cName<<", NCBI_NS_NCBI::eDoNotResetVariant);n";
  1165.                         if ( i->delayed ) {
  1166.                             code.Methods(set_inl) <<
  1167.                                 "    "DELAY_MEMBER".Forget();n";
  1168.                         }
  1169.                         code.Methods(set_inl) <<
  1170.                             "    "<<memberRef<<" = value;n"
  1171.                             "}n"
  1172.                             "n";
  1173.                     }
  1174.                 }
  1175.                 if ( i->memberType == eObjectPointerMember  && !isNullWithAtt) {
  1176.                     methods <<
  1177.                         "void "<<methodPrefix<<"Set"<<i->cName<<"("<<rType<<"& value)n"
  1178.                         "{n"
  1179.                         "    T"<<i->cName<<"* ptr = &value;n";
  1180.                     if ( i->delayed ) {
  1181.                         methods <<
  1182.                             "    if ( "STATE_MEMBER" != "STATE_PREFIX<<i->cName<<" || "DELAY_MEMBER" || "OBJECT_MEMBER" != ptr ) {n";
  1183.                     }
  1184.                     else {
  1185.                         methods <<
  1186.                             "    if ( "STATE_MEMBER" != "STATE_PREFIX<<i->cName<<" || "OBJECT_MEMBER" != ptr ) {n";
  1187.                     }
  1188.                     methods <<
  1189.                         "        Reset();n"
  1190.                         "        ("OBJECT_MEMBER" = ptr)->AddReference();n"
  1191.                         "        "STATE_MEMBER" = "STATE_PREFIX<<i->cName<<";n"
  1192.                         "    }n"
  1193.                         "}n"
  1194.                         "n";
  1195.                     if (i->dataType) {
  1196.                         const CDataType* resolved = i->dataType->Resolve();
  1197.                         if (resolved && resolved != i->dataType) {
  1198.                             CClassTypeStrings* typeStr = resolved->GetTypeStr();
  1199.                             if (typeStr) {
  1200.                                 ITERATE ( TMembers, ir, typeStr->m_Members ) {
  1201.                                     if (ir->simple) {
  1202.                                         string ircType(ir->type->GetCType(
  1203.                                             code.GetNamespace()));
  1204.                                         if (CClassCode::GetDoxygenComments()) {
  1205.                                             setters <<
  1206.                                                 "n"
  1207.                                                 "    /// Select the variant and set its data.n"
  1208.                                                 "    ///n"
  1209.                                                 "    /// @param valuen"
  1210.                                                 "    ///   Reference to variant data.n";
  1211.                                         }
  1212.                                         setters <<
  1213.                                             "    void Set"<<i->cName<<"(const "<<
  1214.                                             ircType<<"& value);n";
  1215.                                         methods <<
  1216.                                             "void "<<methodPrefix<<"Set"<<
  1217.                                             i->cName<<"(const "<<ircType<<
  1218.                                             "& value)n"
  1219.                                             "{n";
  1220.                                         methods <<
  1221.                                             "    Set" << i->cName <<
  1222.                                             "() = value;n"
  1223.                                             "}n"
  1224.                                             "n";
  1225.                                     }
  1226.                                 }
  1227.                             }
  1228.                         }
  1229.                     }
  1230.                 }
  1231.             }
  1232.             setters <<
  1233.                 "n";
  1234.         }
  1235.     }
  1236.     // generate variants data
  1237.     {
  1238.         code.ClassPrivate() <<
  1239.             "    // datan";
  1240.         if (haveAttlist) {
  1241.             ITERATE ( TVariants, i, m_Variants ) {
  1242.                 if (i->attlist) {
  1243.                     code.ClassPrivate() <<
  1244.                         "    "<<ncbiNamespace<<"CRef< T"<<i->cName<<" > m_"<<i->cName<<";n";
  1245.                 }
  1246.             }
  1247.         }
  1248.         if ( haveUnion ) {
  1249.             code.ClassPrivate() << "    union {n";
  1250.             ITERATE ( TVariants, i, m_Variants ) {
  1251.                 if ( i->memberType == eSimpleMember ) {
  1252.                     if (!x_IsNullType(i)) {
  1253.                         code.ClassPrivate() <<
  1254.                             "        T"<<i->cName<<" m_"<<i->cName<<";n";
  1255.                     }
  1256.                 }
  1257.                 else if ( i->memberType == ePointerMember ) {
  1258.                     code.ClassPrivate() <<
  1259.                         "        T"<<i->cName<<" *m_"<<i->cName<<";n";
  1260.                 }
  1261.             }
  1262.             if ( haveString ) {
  1263.                 code.ClassPrivate() <<
  1264.                     "        "STRING_TYPE_FULL" *"STRING_MEMBER";n";
  1265.             }
  1266.             if ( haveObjectPointer ) {
  1267.                 code.ClassPrivate() <<
  1268.                     "        "OBJECT_TYPE_FULL" *"OBJECT_MEMBER";n";
  1269.             }
  1270.             code.ClassPrivate() <<
  1271.                 "    };n";
  1272.         }
  1273.         else if ( haveString ) {
  1274.             code.ClassPrivate() <<
  1275.                 "    "STRING_TYPE_FULL" "STRING_MEMBER";n";
  1276.         }
  1277.         else if ( haveObjectPointer ) {
  1278.             code.ClassPrivate() <<
  1279.                 "    "OBJECT_TYPE_FULL" *"OBJECT_MEMBER";n";
  1280.         }
  1281.         if ( delayed ) {
  1282.             code.ClassPrivate() <<
  1283.                 "    mutable "DELAY_TYPE_FULL" "DELAY_MEMBER";n";
  1284.         }
  1285.     }
  1286.     // generate type info
  1287.     methods <<
  1288.         "// helper methodsn"
  1289.         "n"
  1290.         "// type infon";
  1291.     if ( haveUserClass )
  1292.         methods << "BEGIN_NAMED_BASE_CHOICE_INFO";
  1293.     else
  1294.         methods << "BEGIN_NAMED_CHOICE_INFO";
  1295.     methods <<
  1296.         "(""<<GetExternalName()<<"", "<<classPrefix<<GetClassNameDT()<<")n"
  1297.         "{n";
  1298.     if ( !GetModuleName().empty() ) {
  1299.         methods <<
  1300.             "    SET_CHOICE_MODULE(""<<GetModuleName()<<"");n";
  1301.     }
  1302.     if ( delayed ) {
  1303.         methods <<
  1304.             "    SET_CHOICE_DELAYED();n";
  1305.     }
  1306.     {
  1307.         // All or none of the choices must be tagged
  1308.         bool useTags = false;
  1309.         bool hasUntagged = false;
  1310.         // All tags must be different
  1311.         map<int, bool> tag_map;
  1312.         ITERATE ( TVariants, i, m_Variants ) {
  1313.             // Save member info
  1314.             if ( i->memberTag >= 0 ) {
  1315.                 if ( hasUntagged ) {
  1316.                     NCBI_THROW(CDatatoolException,eInvalidData,
  1317.                         "No explicit tag for some members in " +
  1318.                         GetModuleName());
  1319.                 }
  1320.                 if ( tag_map[i->memberTag] ) {
  1321.                     NCBI_THROW(CDatatoolException,eInvalidData,
  1322.                         "Duplicate tag: " + i->cName +
  1323.                         " [" + NStr::IntToString(i->memberTag) + "] in " +
  1324.                         GetModuleName());
  1325.                 }
  1326.                 tag_map[i->memberTag] = true;
  1327.                 useTags = true;
  1328.             }
  1329.             else {
  1330.                 hasUntagged = true;
  1331.                 if ( useTags ) {
  1332.                     NCBI_THROW(CDatatoolException,eInvalidData,
  1333.                         "No explicit tag for " + i->cName + " in " +
  1334.                         GetModuleName());
  1335.                 }
  1336.             }
  1337.             methods << "    ADD_NAMED_";
  1338.             bool isNull = x_IsNullType(i);
  1339.             if (isNull) {
  1340.                 methods << "NULL_";
  1341.             }
  1342.             
  1343.             bool addNamespace = false;
  1344.             bool addCType = false;
  1345.             bool addEnum = false;
  1346.             bool addRef = false;
  1347.             switch ( i->memberType ) {
  1348.             case ePointerMember:
  1349.                 methods << "PTR_";
  1350.                 addRef = true;
  1351.                 break;
  1352.             case eObjectPointerMember:
  1353.                 methods << "REF_";
  1354.                 addCType = true;
  1355.                 break;
  1356.             case eSimpleMember:
  1357.                 if ( i->type->GetKind() == eKindEnum ) {
  1358.                     methods << "ENUM_";
  1359.                     addEnum = true;
  1360.                     if ( !i->type->GetNamespace().IsEmpty() &&
  1361.                          code.GetNamespace() != i->type->GetNamespace() ) {
  1362.                         _TRACE("EnumNamespace: "<<i->type->GetNamespace()<<" from "<<code.GetNamespace());
  1363.                         methods << "IN_";
  1364.                         addNamespace = true;
  1365.                     }
  1366.                 }
  1367.                 else if ( i->type->HaveSpecialRef() ) {
  1368.                     addRef = true;
  1369.                 }
  1370.                 else {
  1371.                     methods << "STD_";
  1372.                 }
  1373.                 break;
  1374.             case eStringMember:
  1375.                 if ( haveUnion ) {
  1376.                     methods << "PTR_";
  1377.                     addRef = true;
  1378.                 }
  1379.                 else if ( i->type->HaveSpecialRef() ) {
  1380.                     addRef = true;
  1381.                 }
  1382.                 else {
  1383.                     methods << "STD_";
  1384.                 }
  1385.                 break;
  1386.             }
  1387.             if (i->attlist) {
  1388.                 methods << "MEMBER("";
  1389.             } else {
  1390.                 methods << "CHOICE_VARIANT("";
  1391.             }
  1392.             methods <<i->externalName<<""";
  1393.             if (!isNull) {
  1394.                 methods <<", ";
  1395.             }
  1396.             switch ( i->memberType ) {
  1397.             case eObjectPointerMember:
  1398.                 if (i->attlist) {
  1399.                     methods << "m_" << i->cName;
  1400.                 } else {
  1401.                     methods << OBJECT_MEMBER;
  1402.                 }
  1403.                 break;
  1404.             case eStringMember:
  1405.                 methods << STRING_MEMBER;
  1406.                 break;
  1407.             default:
  1408.                 if (!isNull) {
  1409.                     methods << "m_"<<i->cName;
  1410.                 }
  1411.                 break;
  1412.             }
  1413.             if ( addNamespace )
  1414.                 methods << ", "<<i->type->GetNamespace();
  1415.             if ( addCType )
  1416.                 methods << ", "<<i->type->GetCType(code.GetNamespace());
  1417.             if ( addEnum )
  1418.                 methods << ", "<<i->type->GetEnumName();
  1419.             if ( addRef )
  1420.                 methods << ", "<<i->type->GetRef(code.GetNamespace());
  1421.             methods <<")";
  1422.             
  1423.             if ( i->delayed ) {
  1424.                 methods << "->SetDelayBuffer(MEMBER_PTR(m_delayBuffer))";
  1425.             }
  1426.             if (i->noPrefix) {
  1427.                 methods << "->SetNoPrefix()";
  1428.             }
  1429.             if (i->attlist) {
  1430.                 methods << "->SetAttlist()";
  1431.             }
  1432.             if (i->noTag) {
  1433.                 methods << "->SetNotag()";
  1434.             }
  1435.             if ( i->memberTag >= 0 ) {
  1436.                 methods << "->GetId().SetTag(" << i->memberTag << ")";
  1437.             }
  1438.             methods << ";n";
  1439.         }
  1440.     }
  1441.     methods <<
  1442.         "}n"
  1443.         "END_CHOICE_INFOn"
  1444.         "n";
  1445. }
  1446. CChoiceRefTypeStrings::CChoiceRefTypeStrings(const string& className,
  1447.                                              const CNamespace& ns,
  1448.                                              const string& fileName)
  1449.     : CParent(className, ns, fileName)
  1450. {
  1451. }
  1452. END_NCBI_SCOPE