To use the Code DOM, you can create your Code DOM tree, and give it to the Eiffel Code DOM to generate the Eiffel code associated.
First of all, we will have to create a valid Code DOM tree. Here is the code to create a valid code DOM in Eiffel.
create_code_dom_tree: SYSTEM_DLL_CODE_COMPILE_UNIT is -- create codeDOM tree local l_compile_unit: SYSTEM_DLL_CODE_COMPILE_UNIT l_namespace: SYSTEM_DLL_CODE_NAMESPACE l_class_1, l_class_2, l_class_3: SYSTEM_DLL_CODE_TYPE_DECLARATION l_parent_class: SYSTEM_DLL_CODE_TYPE_REFERENCE l_sys: SYSTEM_DLL_CODE_NAMESPACE_IMPORT added: INTEGER l_attribute: SYSTEM_DLL_CODE_MEMBER_FIELD l_procedure: SYSTEM_DLL_CODE_MEMBER_METHOD l_type_return_function: SYSTEM_DLL_CODE_TYPE_REFERENCE l_parameter: SYSTEM_DLL_CODE_PARAMETER_DECLARATION_EXPRESSION l_comments: SYSTEM_DLL_CODE_COMMENT_STATEMENT l_variable: SYSTEM_DLL_CODE_VARIABLE_DECLARATION_STATEMENT do -- defining compile unit createl_compile_unit.make -- adding referenced assemblies added := l_compile_unit.referenced_assemblies.add (("C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\mscorlib.dll").to_cil) added := l_compile_unit.referenced_assemblies.add (("C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\system.dll").to_cil) added := l_compile_unit.referenced_assemblies.add (("C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\system.xml.dll").to_cil) -- defining namespace "sample" create l_namespace.make_from_name (("sample").to_cil) -- importing namespace create l_sys.make_from_name_space (("system").to_cil) l_namespace.imports.add (l_sys) -- adding `namespace' to `compile_unit' added := l_compile_unit.namespaces.add (l_namespace) --------------------------- CLASS_1 --------------------------- -- Defining class create l_class_1.make_from_name (("CLASS_1").to_cil) -- adding comments to 'CLASS_2' create l_comments.make_from_text_and_doc_comment (("Class with two attributes").to_cil, true) added := l_class_1.comments.add (l_comments) -- adding class to 'l_namespace' added := l_namespace.types.add (l_class_1) -- adding an attribute to 'l_class_1' create l_attribute.make_from_type_and_name_2 (("System.Int32").to_cil, ("my_attribute").to_cil) added := l_class_1.members.add (l_attribute) -- adding an other attribute to 'l_class_1' create l_attribute.make_from_type_and_name_2 (("System.Double").to_cil, ("my_2_attribute").to_cil) added := l_class_1.members.add (l_attribute) --------------------------- CLASS_2 --------------------------- -- Defining class CLASS_2 create l_class_2.make_from_name (("CLASS_2").to_cil) -- adding comments to 'CLASS_2' create l_comments.make_from_text_and_doc_comment (("This class inherit CLASS_1, and is client of CLASS_3").to_cil, true) added := l_class_2.comments.add (l_comments) -- adding 'class_2' to 'namespace' added := l_namespace.types.add (l_class_2) -- adding an attribute to 'l_class_2' create l_attribute.make_from_type_and_name_2 (("CLASS_1").to_cil, ("my_attribute_class_2").to_cil) added := l_class_2.members.add (l_attribute) -- adding comments to attribute create l_comments.make_from_text (("This comment is from the DOM").to_cil) added := l_attribute.comments.add (l_comments) -- adding inheritance : 'l_class_1' is parent 'class_2' createl_parent_class.make_from_type_name (l_class_1.name) --parent_class.set_array_element_type (feature_clause) added := l_class_2.base_types.add_code_type_reference (l_parent_class) -- adding an other attribute to 'class_2' create l_attribute.make_from_type_and_name_2 (("CLASS_3").to_cil, ("my_2_attribute_class_2").to_cil) added := l_class_2.members.add (l_attribute) -- adding procedure my_procedure to `class_2' createl_procedure.make added := l_class_2.members.add (l_procedure) -- set `my_procedure' l_procedure.set_name (("my_procedure").to_cil) create l_parameter.make_from_type_and_name_2 (("System.Single").to_cil, ("param_1").to_cil) added := l_procedure.parameters.add (l_parameter) create l_parameter.make_from_type_and_name_2 (("System.Double").to_cil, ("param_2").to_cil) added := l_procedure.parameters.add (l_parameter) create l_variable.make_from_type_and_name_2 (("System.Int32").to_cil, ("my_local_variable").to_cil) added := l_procedure.statements.add_code_statement (l_variable) -- adding comments to procedure create l_comments.make_from_text (("This is a function comment").to_cil) added := l_procedure.comments.add (l_comments) -- adding function my_procedure to `class_2' create l_procedure.make l_procedure.set_name (("my_function").to_cil) create l_parameter.make_from_type_and_name_2 (("System.Int32").to_cil, ("param_1").to_cil) added := l_procedure.parameters.add (l_parameter) create l_parameter.make_from_type_and_name_2 (("System.Double").to_cil, ("param_2").to_cil) added := l_procedure.parameters.add (l_parameter) create l_type_return_function.make_from_type_name (("System.Boolean").to_cil) l_procedure.set_return_type (l_type_return_function) added := l_class_2.members.add (l_procedure) --------------------------- CLASS_3 --------------------------- -- Defining class create l_class_3.make_from_name (("CLASS_3").to_cil) -- adding comments to 'CLASS_2' create l_comments.make_from_text_and_doc_comment (("Class with two attributes").to_cil, true) added := l_class_3.comments.add (l_comments) -- adding class to 'l_namespace' added := l_namespace.types.add (l_class_3) -- adding an attribute to 'l_class_3' create l_attribute.make_from_type_and_name_2 (("System.String").to_cil, ("my_attribute").to_cil) added := l_class_3.members.add (l_attribute) -- adding an other attribute to 'l_class_3' create l_attribute.make_from_type_and_name_2 (("System.Object").to_cil, ("my_2_attribute").to_cil) added := l_class_3.members.add (l_attribute) Result := l_compile_unit end
Then, we have to reference the Eiffel code DOM dll, in the project. Use Project\Project settings, and select the .NET Assemblies tab. Click the Add button, scroll down the list of GAC Assemblies and select ISE.CodedomProvider.ASP.
Now, we simply have to create an instance of the Eiffel_code_generator, and call the function `generate_code_from_compile_unit' with the above code DOM tree.
local eiffel_code_generator: SYSTEM_DLL_ICODE_GENERATOR do eiffel_code_generator := (create {EIFFEL_CODE_DOM_PROVIDER}.default_create).create_generator eiffel_code_generator.generate_code_from_compile_unit (create_code_dom_tree, Void, Void) end
We will end up with three Eiffel files (class_1.e, class_2.e, class_3.e) generated in the current directory.
Note: When you call the Eiffel code DOM generator, the second argument (STREAM) can be Void. This stream is normally used to put all the generated code. But, an Eiffel system requires each class to be generated in separated files. Then, as a code DOM tree can contain more than one class, the Eiffel code DOM will automatically generate the files it needs to generate the code. These files are generated in the current directory.
Note 2: The option parameter (third parameter) does not have any influence on the code generation, because there is only one syntax style in Eiffel!
Note 3: Make sure that the paths to the assemblies are correct.
wsdl.exe and xsd.exe are two tools given with the Framework SDK. They uses the code DOM to generate code in a given language. So that, you can specify the language you want the code to be generated in. The option to use is 'language' and you have to specify the fully-qualified name for a class implementing System.CodeDom.Compiler.CodeDomProvider. Here is the command line option to use the Eiffel Code DOM, and then generate Eiffel code:
/language:"ISE.codedomprovider.EIFFEL_CODE_DOM_PROVIDER, ISE.CodeDomProvider.ASP, Version=5.2.0.0, Culture=neutral, PublicKeyToken=def26f296efef469"
wsdl generates the source code associated to a given URL.
examples:
wsdl /language:"..." http://www.capescience.com/webservices/airportweather/AirportWeather.wsdl wsdl /language:"..." http://www.nanonull.com/TimeService/TimeService.asmx?wsdl
Both examples will create two ".e" files in the current directory.
Note: The out option is unavailable with the Eiffel Code DOM. In fact, in the previous chapter, we saw that the Code DOM does not uses the input stream to generate the code and generate the code in the current directory. It is the same here, and the associated source code will be generated in the current directory.
Note 2: wsdl will also generate an ".ace" file. This file is empty, and has no interest.
xsd generates the source code associated to a given xsd file.
We need an xsd file. We will start with the following xml file (books.xml) that we will convert into an xsd file.
<?xml version="1.0"?> <bookstore xmlns="generic"> <book genre="autobiography"> <title>The Autobiography of Benjamin Franklin</title> <author> <first-name>Ben</first-name> <last-name>Franklin</last-name> </author> <price>89.88</price> </book> <book genre="novel"> <title>The Confidence Man</title> <author> <first-name>John</first-name> <last-name>Melville</last-name> </author> <price>11.99</price> </book> </bookstore>
From the xml code above (books.xml), we can generate an xsd file (books.xsd) running the following command line:
xsd books.xml
When we have the xsd file, you can generate the Eiffel code corresponding, running this command line:
xsd /language:"..." books.xsd /c
The Eiffel code is generated in three different files (bookstore.e, bookstore_book.e, bookstore_book_author.e).
bookstore.e
indexing description: "<remarks/>" attribute: create {XML_XML_TYPE_ATTRIBUTE}.make [["namespace", ("generic").to_cil]] end, create {XML_XML_ROOT_ATTRIBUTE}.make_from_element_name (("bookstore").to_cil) [["namespace", ("generic").to_cil], ["is_nullable", False]] end class BOOKSTORE create {NONE} feature -- Access Items: NATIVE_ARRAY [BOOKSTORE_BOOK] -- | <remarks/> indexing attribute: create {XML_XML_ELEMENT_ATTRIBUTE}.make_from_element_name (("book").to_cil) end end end -- BOOKSTORE
bookstore_book.e
indexing description: "<remarks/>" attribute: create {XML_XML_TYPE_ATTRIBUTE}.make [["namespace", ("generic").to_cil]] end class BOOKSTORE_BOOK create {NONE} feature -- Access title: SYSTEM_STRING -- | <remarks/> price: SYSTEM_STRING -- | <remarks/> author: NATIVE_ARRAY [BOOKSTORE_BOOK_AUTHOR] -- | <remarks/> indexing attribute: create {XML_XML_ELEMENT_ATTRIBUTE}.make_from_element_name (("author").to_cil) end end genre: SYSTEM_STRING -- | <remarks/> indexing attribute: create {XML_XML_ATTRIBUTE_ATTRIBUTE}.make [["form", feature {XML_XML_SCHEMA_FORM}.Unqualified]] end end end -- BOOKSTORE_BOOK
bookstore_book_author.e
indexing description: "<remarks/>" attribute: create {XML_XML_TYPE_ATTRIBUTE}.make [["namespace", ("generic").to_cil]] end class BOOKSTORE_BOOK_AUTHOR create {NONE} feature -- Access firstname: SYSTEM_STRING -- | <remarks/> indexing attribute: create {XML_XML_ELEMENT_ATTRIBUTE}.make_from_element_name (("first-name").to_cil) end end lastname: SYSTEM_STRING -- | <remarks/> indexing attribute: create {XML_XML_ELEMENT_ATTRIBUTE}.make_from_element_name (("last-name").to_cil) end end end -- BOOKSTORE_BOOK_AUTHOR
Note: xsd prompt that the code is generated in the file books.ace. As we saw in the previous chapters, this file is useless, and we are only interested in the three ".e" files generated in the current directory.