: code generator tutorial

Lesson 5: Generate Proxy Types

We just spent quite a bit of time figuring out how to instruct the code generator what types we are interested in. It is time to put our knowledge to the test and generate some C++ proxy types.

In this lesson we will import the java.lang.Object type and see what happens when we generate. Then we will import the java.lang.Class type, generate again, and compare the outcomes.

Step by Step Instructions

  1. Start the Code Generator GUI and Create a New Model

    Please revisit the first two lessons if you are uncertain how to do this or if you run into problems. Otherwise, change the model name to Object Test and import the java.lang.Object type.

    Save the model to a directory of your choice. We do this so the modelFile and modelDir properties become defined.

  2. Generate C++ proxy types

    Select the "To C++ Proxy Types" from the Transform menu. You should see some log statements in your console that indicate that something has happened.

  3. Verify That Proxies Were Generated

    If you recall something you learned in a previous lesson, the default target directory is calculated from the modelDir property. C++ proxy types should be located in the generated subdirectory of the directory in which your model file is stored.

    Even though the model contained a lot of types (over 500 with the JRE that I had configured), there are only a handful of C++ types that were generated. With the JRE I used, I see proxy types for

        java.lang.Object
        java.lang.String
        java.lang.Class
        java.lang.InterruptedException 

    For every enabled type in the model you get a .h header and a .cpp implementation file.

    For every package that contained generating types you also get a "namespace include" file. This is a convenience file that acts similarly to a "package import" statement in Java: it makes all types in the namespace available by their unqualified typename.

    You also get a variety of optional build support files as well as API documentation in a doc subdirectory. You can disable the generation of all these additional files through various model properties but they are enabled by default.

  4. Import java.lang.Class and Regenerate Proxy Types

    So far, so good. Nothing terribly unexpected has happened. Now we import java.lang.Class, a type that is already in the model and even enabled in the model; we just saw that a proxy type is being generated for it.

    Let's regenerate by again selecting the "To C++ Proxy Types" from the Transform menu.

    When you inspect the generated code you see a much larger set of proxy types. For the JRE version I used, I got:

        java.io.InputStream
        java.io.Serializable
        java.lang.annotation.Annotation
        java.lang.Class
        java.lang.ClassLoader
        java.lang.ClassNotFoundException
        java.lang.IllegalAccessException
        java.lang.InstantiationException
        java.lang.InterruptedException
        java.lang.NoSuchFieldException
        java.lang.NoSuchMethodException
        java.lang.Object
        java.lang.Package
        java.lang.reflect.AnnotatedElement
        java.lang.reflect.AnnotatedType
        java.lang.reflect.Constructor
        java.lang.reflect.Field
        java.lang.reflect.Method
        java.lang.reflect.Type
        java.lang.reflect.TypeVariable
        java.lang.SecurityException
        java.lang.String
        java.net.URL
        java.security.ProtectionDomain

    This might surprise you. Why did we get so many types when all we did was import a type that was already part of the model? The difference stems from the intent we expressed when we imported Class.

    When we imported it by name we told the code generator: "I am interested in using java.lang.Class's API." That implied that all of its publicly referenced types needed to be enabled as well. Class is a much beefier type than Object, so we ended up with many more types.

    For our next exercise we are going to generate the proxies from the command line without opening the GUI. For that we need the model file and we need a clean generation area so we can tell that it worked.

  5. Save the Model and Exit Code Generator GUI

    You can choose the same or a different filename, then exit the GUI.

  6. Delete the Generated Proxies
    rm -rf <modelDir>/generated
    del <modelDir>/generated
  7. Generate Using the Command Line

    This is the first time in the tutorial that we will be using the command line version to do some real work for us. In the second lesson we learned how a model can be reopened in the GUI from the command line. While we started this action from the command line, it really translated into a GUI invocation.

    Now we're going full command line! Assuming you're still in the code generator's bin directory, execute the following command:

    ./xmog -cpp "<modelFile>"
    xmog -cpp "<modelFile>"

    After a brief wait, the code generation should be complete and you should be able to see the generated proxy types in their previous location.

    Essentially, we opened the model file, just as we did in the second lesson, but then we had a command performed on it—in our case the -cpp command to generate C++ proxy types. The mere fact that we gave the code generator a command caused it to switch into command line mode and exit after completing the command.

    You have now generated proxy types both from the GUI and from the CLI version of the code generator. There is a third way, using ANT, but we're not going to do that in this basic lesson because not everyone is interested in this variant. You can find out more about it in the code generator's ANT Reference.

Take-Away Points

  1. Importing a type into the model is a powerful gesture that can cause a lot of types to be enabled.
  2. You don't have to open he GUI to generate proxy types.
  3. Use the -cpp command to generate proxy types from the command line.