= Vert.x Codegen

Vert.x Codegen is an annotation processing tool for processing Vert.x API and create API in different JVM lauguages.

Vert.x polyglot langs use code generation for creating https://en.wikipedia.org/wiki/Shim_(computing)[shim] for APIs,
that are thin wrappers in front of the API type.

A shim is the adaptation of a Vert.x API to a JVM language. A shim uses code generation to generate
wrappers in its own language delegating to the Vert.x API, code generation is based on Java annotation
processing.

== Vert.x API

A Vert.x API is a collection of Java types annotated with Codegen annotations that respect a set of constraints to
ensure easy portability of the API to most languages and enable an asynchronous programming model. Such collection
of API types are grouped in modules.

=== Modules

A module contains a collection of Vert.x API and data objects declarations., some shim uses modules for organizing
and loading the Vert.x api:

- the JavaScript shim uses https://en.wikipedia.org/wiki/CommonJS[CommonJS] modules
- the Ruby shim uses Ruby modules
- Ceylon uses Ceylon native modules

NOTE: so far in Java or Groovy the notion of module is not used because it delegates loading to classloaders.

Modules are declared by annotating a Java package with a {@link io.vertx.codegen.annotations.ModuleGen @ModuleGen}
annotation.

[source,java]
----
@ModuleGen(name = "acme", groupPackage="com.acme")
package com.acme.myservice;

import io.vertx.codegen.annotations.ModuleGen;
----

The module _name_ is a namespace for shims that don't support package like naming, like JavaScript `acme-js`
or Ruby `acme`, whereas the _group package_ determines the created package, for instance
`com.acme.groovy.myservice` in Groovy. The group package must be a prefix of the annotated module.

Vert.x modules use the reserved name _vertx-XYZ_ and the reserved group package _io.vertx_.

An API module contains various Vert.x types annotated with {@link io.vertx.codegen.annotations.VertxGen}
or {@link io.vertx.codegen.annotations.DataObject}.

NOTE: using Maven coordinates for name and group package is encouraged: the name corresponding to the
Maven _artifactId_ and the group package corresponding to the `groupId`.

=== Data objects

A _Data object_ is a type that can be converted back and forth to a Json type.

You can declare data objects by:

* Defining a mapper in the `META-INF/vertx/json-mappers.properties` file
* Or annotating the type itself with `@DataObject`

==== Json mappers

A json mapper for type `T` is a method that maps any object or enum of type `Type`, where `J` can be:

* `JsonArray` or `JsonObject`
* a concrete type extending `Number` such as `Long` or `Double`
* `String`
* `Boolean`

Json mapped types can be used anywhere a json types used are.

A json mapper turns any Java type into a data object type.

===== Object
You can declare them as public static methods:

[source,java]
----
package com.example;

public class MyMappers {

  public static String serialize(ZonedDateTime date) {
    return date.toString();
  }

  public static ZonedDateTime deserialize(String s) {
    return ZonedDateTime.parse(s);
  }
}
----

These mappers needs to be declared in a `META-INF/vertx/json-mappers.properties` file as follow:

[source]
----
java.time.ZonedDateTime.serializer=com.example.MyMappers#serializeZonedDateTime
java.time.ZonedDateTime.deserializer=com.example.MyMappers#deserializedZoneDateTime
----

Again the mappers needs to be declared in a `json-mappers.properties` file:

[source]
----
java.time.ZonedDateTime.serializer=com.example.MyMappers#SERIALIZER
java.time.ZonedDateTime.deserializer=com.example.MyMappers#DESERIALIZER
----

===== Enum

Enum can be define with values parameters passed to a constructor. In this use case, you can't use default behavior of codegen (#valueOf() and #name()), you need to define like Object `serializer` and `deserializer`.

[source,java]
----
package com.example;

public enum MyEnumWithCustomFactory {
  DEV("dev", "development"), ITEST("itest", "integration-test");

  private String[] names = new String[2];

  MyEnumWithCustomFactory(String pShortName, String pLongName) {
    names[0] = pShortName;
    names[1] = pLongName;
  }

  public String getLongName() {
    return names[1];
  }

  public String getShortName() {
    return names[0];
  }

  public static MyEnumWithCustomFactory of(String pName) {
    for (MyEnumWithCustomFactory item : MyEnumWithCustomFactory.values()) {
      if (item.names[0].equalsIgnoreCase(pName) || item.names[1].equalsIgnoreCase(pName)
              || pName.equalsIgnoreCase(item.name())) {
        return item;
      }
    }
    return DEV;
  }

}
----
You can declare them as public static methods:
[source,java]
----
public static String serialize(MyEnumWithCustomFactory value) {
  return value.getLongName();
}

public static MyEnumWithCustomFactory deserialize(String value) {
  return MyEnumWithCustomFactory.of(value);
}
----
These mappers needs to be declared in a `META-INF/vertx/json-mappers.properties` file as follow:
----
com.example.MyEnumWithCustomFactory.serializer=com.example.MyEnumWithCustomFactory#serialize
com.example.MyEnumWithCustomFactory.deserializer=com.example.MyEnumWithCustomFactory#deserialize
----

==== `@DataObject` annotated types

A `@DataObject` annotated type is a Java class with the only purpose to be a container for data.

A converter instance is automatically generated when the class is annotated with `@DataObject(generateConverter = true)`

Data object annotated classes can also inherit from other data objects annotated types.

===== Properties

Data object annotated types properties are declared via _getters_, _setters_ or _adders_:

.a getter and a setter
[source,java]
----
public String getHost() {
  return host;
}

public WebServerOptions setHost(String host) {
  this.host = host;
  return this;
}
----

Here is the list of supported property single valued types:

1. any primitive or boxed primitive type
2. `java.lang.String`
3. `io.vertx.core.json.JsonObject` and `io.vertx.core.json.JsonArray`
4. the specific `io.vertx.core.buffer.Buffer` type providing support for byte array
5. Java enums
6. another data object

In addition a data object can also have multi-valued properties as a `java.util.List<V>`/`java.util.Set<V>` or a
`java.util.Map<String, V>` where the `<V>` is a supported single valued type or `java.lang.Object`
that stands for anything converted by `io.vertx.core.json.JsonObject` and `io.vertx.core.json.JsonArray`.

List/set multi-valued properties can be declared via a _setter_ :

.a multi valued setter
[source,java]
----
public WebServerOptions setCertificates(List<String> certificates) {
  this.certificates = certificates;
  return this;
}
----

Or an _adder_ :

.a multi valued adder
[source,java]
----
public WebServerOptions addCertificate(String certificate) {
  this.certificates.add(certificate);
  return this;
}
----

Map properties can only be declared with a _setter_.

NOTE: these examples uses a _fluent_ return types for providing a better API, this is not mandatory but
encouraged.

==== Json -> Data Object conversion

When a data object has an associated deserializer, it can be instantiated from a json value and is said _deserializable_.
For POJO to json object mapping, although there are no strict rules of mapping between the data object properties and
the json structure, it is a good thing to follow a common mapping for users using json data objects (like in JavaScript shim).

In particular json object properties should be named after properties according to JavaBean conversion rules:

- a single valued property follows the JavaBean convention
- a multi valued property declared with a list setter follows the same convention
- a multi valued property declared with an adder must use a singular form and the json property name gets a trailing _s_

In all case, property names are _normalized_, i.e:

- _red_ -> _red_
- _Red_ -> _red_
- _URL_ -> _url_
- _URLFactory_ -> _urlFactory_

==== Data object -> json conversion

When a data object has an associated serializer, it can be converted to the json format and is said _serializable_.
Vert.x API types have restriction in the declared method return types, a jsonifiable data object can be used in
Vert.x API method return types or handlers because it can be converted to a json format, otherwise it is not permitted.

===== Data object converter

The data object/json conversion can be tedious and error prone.

Vertx-codegen can automate it, generating for you an auxiliary class that implements the conversion logic.
The generated converter handles the type mapping as well as the json naming convention.

Converters are generated when the data object is annotated with `@DataObject(generateConverter=true)`. The
generation happens for the data object properties, not for the ancestor properties, unless `inheritConverter`
is set: `@DataObject(generateConverter=true,inheritConverter=true)`.

The converter is named by appending the `Converter` suffix to the data object class name, e.g,
`ContactDetails` -> `ContactDetailsConverter`. The generated converter has two static methods:

- `public static void fromJson(JsonObject json, ContactDetails obj)`
- `public static void toJson(ContactDetails obj, JsonObject json)`

The former should be used in the json constructor, the later in the `toJson` method.

[source,java]
----
public ContactDetails(JsonObject json) {
  this();
  ContactDetailsConverter.fromJson(json, this);
}

public JsonObject toJson() {
  JsonObject json = new JsonObject();
  ContactDetailsConverter.toJson(this, json);
  return json;
}
----

=== Building types

A few types used throughout Vert.x API are not annotated with `@VertxGen` yet are used for building
the API:

- `io.vertx.core.Handler`
- `java.util.function.Function`
- `io.vertx.core.AsyncResult`
- `io.vertx.core.json.JsonObject`
- `io.vertx.core.json.JsonArray`
- `java.lang.Object`
- `java.lang.Throwable`
- `java.lang.Void`
- `java.lang.String`
- `java.util.List`
- `java.util.Set`
- `java.util.Map`
- primitive and boxed primitives

These types are usually handled natively by shims, for instance the `Handler` type is a function in JavaScript,
a block in Ruby, the same `Handler` in Groovy, a function in Ceylon, etc...

=== Generated types

An API type is a Java interface annotated with {@link io.vertx.codegen.annotations.VertxGen}.

Vert.x provides a async / non blocking / polyglot programming model, code generated API shall follow some
rules to make this possible:

1. the API must be described as a set of Java interfaces, classes are not permitted
2. nested interfaces are not permitted
3. all interfaces to have generation performed on them must be annotated with the `io.vertx.codegen.annotations.VertxGen` annotation
4. fluent methods (methods which return a reference to `this`) must be annotated with the `io.vertx.codegen.annotations.Fluent` annotation
5. methods where the return value must be cached in the API shim must be annotated with the `io.vertx.codegen.annotations.CacheReturn` annotation
6. only certain types are allowed as parameter or return value types for any API methods
7. custom enums should be annotated with `@VertxGen`, although this is not mandatory to allow the usage of existing Java enums
8. nested enums are not permitted
9. default implementations are allowed

An API type can be generic or declare generic methods, type parameters must be unbounded, e.g
`<N extends Number>` is forbidden.

In the perspective of codegen, Java types can be categorized as follow:

. _basic_ type : any primitive/boxed type or `java.lang.String`
. _json_ type : `io.vertx.core.json.JsonObject` or `io.vertx.core.json.JsonArray`
. _api_ type : any type annotated with `io.vertx.codegen.annotations.VertxGen`
. _data object_ type : any data object type as defined above
. _enum_ type : any Java enum
. _collection_ type : `java.util.List<V>`, `java.util.Set<V>` or `java.util.Map<String, V>`
. _java_ type : any other type that can be represented as a Java class. Java types declarations are only permitted
in interfaces allowing them (`@VertxGen(allowJavaTypes = true)`)

Parameterized types are supported but wildcards are not, that is the following type arguments declarations
are *forbidden*:

- `Foo<?>`
- `Foo<? extends Number>`
- `Foo<? super Number>`

Parameterized types are only supported for _api_ generic types, _collection_ types and _java_ types.

Type variables are allowed and carry a special meaning: a type variable is a dynamic form of a _basic_ type and
_json_ type.

_java_ types should be used wisely because they provide a limited compatibility with Vert.x generators.

==== Inheritance

_api_ type can extend other _api_ types.

An _api_ type can either be *concrete* or *abstract*, such information is important for languages not
supporting multiple class inheritance like Groovy:

- _api_ types annotated with {@link io.vertx.codegen.annotations.VertxGen}`(concrete = false)` are meant to be
extended by *concrete* interfaces an can inherit from *abstract* interfaces only.
- _api_ types annotated with {@link io.vertx.codegen.annotations.VertxGen} or {@link io.vertx.codegen.annotations.VertxGen}`(concrete = true)`
are implemented directly by Vertx and can inherit at most one other *concrete* interface and any *abstract* interface

==== Method parameter types

The following method parameter types are allowed:

. any _basic_ type
. any _api_ type or parameterized _api_ type having type variable parameters
. any _java_ type
. any _json_ type
. the `java.lang.Throwable` type
. any _enum_ type
. any _data object_ that provides a deserializer
. an https://docs.oracle.com/javase/tutorial/java/generics/bounded.html[unbounded type variable], i.e `T extends Number` or `T super Number` are not permitted
. `java.lang.Object`
. a `java.util.List<V>`, `java.util.Set<V>` or `java.util.Map<String, V>` where `<V>` can be a _basic_ type,
a _json_ type, an _api_ type or a `java` type. For list and set `V` can also be an _enum_ type or a _data object_ type

Callback parameters are allowed, i.e types declaring `io.vertx.core.Handler<E>` or
`io.vertx.core.Handler<io.vertx.core.AsyncResult<E>>` where `<E>` can be:

. the `java.lang.Void` type
. any _basic_ type
. any _api_ type
. any _java_ type
. any _json_ type
. the `java.lang.Throwable` type - only for `Handler<R>`
. any _enum_ type
. any _data object_ that provides an serializer
. an https://docs.oracle.com/javase/tutorial/java/generics/bounded.html[unbounded type variable], i.e `T extends Number` or `T super Number` are not permitted
. a `java.util.List<V>`, `java.util.Set<V>` or `java.util.Map<String, V>` where `<V>` can be a _basic_ type,
a _json_ type. For list and set `V` can also be an _API_ type, an _enum_ type or a _data object_ type

Future parameters are allowed, i.e types declaring `io.vertx.core.Future<T>` where `<T>` is valid if and only if `Handler<AsyncResult<T>>` is valid

Function parameters are allowed, i.e types declaring `java.util.function.Function<E, R>` where `<E>` is defined to
be same than for handlers and `<R>` can be:

. any _basic_ type
. any _api_ type
. any _java_ type
. any _json_ type
. the `java.lang.Throwable` type
. any _enum_ type
. any _data object_ that provides a deserializer
. an unbounded type variable
. a `java.util.List<V>`, `java.util.Set<V>` or `java.util.Map<String, V>` where `<V>` can be a _basic_ type,
a _json_ type or a `java` type. For list and set `V` can also be an _API_ type, an _enum_ type or a _data object_ type

==== Method return type

The following return types are allowed:

. `void` type
. any _basic_ type
. any _api_ type or parameterized _api_ type having type variable parameters
. any _java_ type
. any _json_ type
. the `java.lang.Throwable` type
. any _enum_ type
. any _data object_ that provides an serializer
. an https://docs.oracle.com/javase/tutorial/java/generics/bounded.html[unbounded type variable], i.e `T extends Number` or `T super Number` are not permitted
. a `java.util.List<V>`, `java.util.Set<V>` or `java.util.Map<String, V>` where `<V>` can be a _basic_ type,
a _json_ type. For list and set `V` can also be an _API_ type, an _enum_ type or a _data object_ type
. an `Handler<T>` where T is is a among the method parameter types
. an `Handler<AsyncResult<T>>` where `<T>` is a among the method parameter types
.  a `io.vertx.core.Future<T>` where `<T>` is valid if and only if `Handler<AsyncResult<T>>` is valid

==== Method overloading

Some languages don't support method overloading at all. Ruby, JavaScript or  Ceylon to name a few of them.
However the same restriction for Vert.x API would limit API usability.

To accomodate both, overloading is supported when there are no ambiguities between overloaded signatures.
When an API is analyzed an _overload check_ is performed to ensure there is no ambiguity.

Here is an example of possible ambiguity:

.an overload check failure
[source,java]
----
void add(int x, int y);
void add(double x, double y);
----

The JavaScript language use the type number in both cases: at runtime there is no possibility for the
JavaScript shim to know which method to use.

Method declaring `java` types are not checked.

==== Nullable types

Null values have an impact on shim design:

- shims based on value types for dispatching overloaded methods fail for null values, for example a `foo(String)`
method overloaded by a `foo(Buffer)` method invoked with `foo(null)` cannot delegate to the correct underlying method in
JavaScript.
- some shims can leverage this information to provide a better API, for instance an `Optional<String>` Java type or the
`String?` in Ceylon, etc...

Codegen provides the {@link io.vertx.codegen.annotations.Nullable} annotations for annotating types.

Method return type can be {@link io.vertx.codegen.annotations.Nullable}:

[source,java]
----
@Nullable String getAttribute(String name);
----

As well as method parameter type:

[source,java]
----
void close(@Nullable Handler<Void> closeHandler);
----

WARNING: type validation is a non goal of this feature, its purpose is to give hints to the shim
for generating correct code.

These rules apply to {@link io.vertx.codegen.annotations.Nullable} types:

. primitive types cannot be {@link io.vertx.codegen.annotations.Nullable}
. method parameter type can be {@link io.vertx.codegen.annotations.Nullable}
. method return type can be {@link io.vertx.codegen.annotations.Nullable} but not for {@link io.vertx.codegen.annotations.Fluent}
. `io.vertx.core.Handler` type argument can be {@link io.vertx.codegen.annotations.Nullable} but not for
`java.lang.Void` or `io.vertx.core.AsyncResult`
. `io.vertx.core.Handler<io.vertx.core.AsyncResult>` type argument can be {@link io.vertx.codegen.annotations.Nullable}
but not for `java.lang.Void`
. the `java.lang.Object` type is always nullable
. the `<T>` in `<T>` parameter/return, `Handler<T>` or `Handler<AsyncResult<T>>` is implicitly nullable
. the `java.lang.Object` parameter is implicitly nullable
. a method overriding another method `inherits` the {@link io.vertx.codegen.annotations.Nullable} usage of the overriden method
. a method overriding another method cannot declare {@link io.vertx.codegen.annotations.Nullable} in its types

In addition these rules apply to {@link io.vertx.codegen.annotations.Nullable} type arguments:

. methods cannot declare generic api types with nullable type arguments, e.g `<T> void method(GenericApi<Nullable T> api)` is not permitted
. methods can declare nullable collection, e.g `void method(List<Nullable String> list)` is allowed

Besides these rules, nullable types of method parameters have an impact on method overloading: the parameter
at the same position cannot be {@link io.vertx.codegen.annotations.Nullable} more than one time when the number
of method parameters is the same, e.g:

[source,java]
----
void write(@Nullable String s);
void write(@Nullable Buffer s);
----

is not permitted, however:

[source,java]
----
void write(@Nullable String s);
void write(@Nullable String s, String encoding);
----

is permitted because the number of parameters differs.

=== Asynchronous operations

Asynchronous operations can be declared using method with callback or method returning futures.

The default mode declares asynchronous operations with a method having a trailing callback, e.g

[source,java]
----
// A callback methods that declares an synchronous operation yielding to a buffer or a failure
void getValue(Handler<AsyncResult<Buffer>> handler);
----

Callback methods can have a future companion method with a future returning signature:

[source,java]
----
Future<Buffer> getValue();
----

Such method is ignored by codegen because it represents the same asynchronous operation declared by the handler above.

This specific schemes was developed with backward compatibility of Vert.x 3 and Vert.x modules that were developed
in Vert.x 3 and still available in Vert.x 4 use it.

New Vert.x modules developed exclusively for Vert.x 4 can declare methods with only future returning signatures.

The module needs to be declared accordingly:

[source,java]
----
@ModuleGen(name = "acme", groupPackage="com.acme", useFutures = true)
package com.acme.myservice;

import io.vertx.codegen.annotations.ModuleGen;
----

Then asynchronous operation only need to return a Vert.x future.

=== Static methods

Vert.x generated types allow _static_ methods, such methods often plays the role of factory. For instance
`Buffer` instance are obtained by the static method `Buffer.buffer()`, this method is translated to an equivalent
in the shim.

In Javascript:

[source,javascript]
----
var Buffer = require('vertx-js/buffer');
var buf = Buffer.buffer();
----

In Ruby:

[source,ruby]
----
require 'vertx/buffer'
buf = Vertx::Buffer.buffer()
----

In Groovy:

[source,groovy]
----
def buf = io.vertx.groovy.core.Buffer.buffer();
----

=== Ignored methods

Methods annotated with {@link io.vertx.codegen.annotations.GenIgnore} are simply ignored by codegen, this
is useful when the API provides Java specific methods, for instance a method uses a type not permitted
by codegen.

== Shim proxies

A code generated API creates shim proxies delegating method invocation to the API.

.a simplified Buffer API
[source,java]
----
@VertxGen
public interface Buffer {

  static Buffer buffer(String s) {
    return new BufferImpl(s);
  }

  int length();
}
----

A JavaScript generated shim could look like:

.the JavaScript shim
[source,javascript]
----
var JBuffer = io.vertx.core.buffer.Buffer;
var Buffer = function(j_val) {

  // delegate object
  var j_buffer = j_val;
  var that = this;

  this.length = function() {
    return j_buffer.length();
  };
}

Buffer.buffer = function(s) {
  return new Buffer(JBuffer.buffer(s));
}

module.exports = Buffer;
----

The static `buffer` method is translated into the `buffer` method of the `Buffer` module, this method
delegates the call to the Java static method and returns a `Buffer` proxy wrapping the returned buffer.

The instance `length` method is translated into the `length` method of the proxy instance, this method
delegates the call to the Java instance method of the proxied buffer and simply returns the value. The
Nashorn interoperability takes care of converting the `int` type to a JavaScript `Number`.

=== Return values

A shim implements several strategies when returning values from the Vert.x API:

1. a _basic_ value is usually handled by the shim interop
2. an _API_ value creates a proxy to wrap the value
3. a _json_ (object or array) value is translated to the shim equivalent
4. a _data object_ that provides an serializer is converted to a json or an equivalent
5. an _enum_ value is converted to a string or an equivalent
6. a _collection_ is usually translated to the shim equivalent
7. a `java.lang.Throwable` is usually translated to the shim equivalent
8. a type variable is converted dynamically converted to a _basic_ type or a _json_ type
9. an `Handler<T>` value is what is used in the target language to represent an handler, when this handler is called
it invokes the handler with the value converted using the argument value rules
10. an `Handler<AsyncResult<T>>` value is what is used in the target language to represent an async result handler, when this handler
is _succeeded_ it invokes the handler with the `AsyncResult<T>` wrapping the converted value using the argument value rules,
otherwise it invokes the handler with the `AsyncResult<T>` wrapping the throwable

=== Argument values

A shim implements several strategies when passing values to the Vert.x API:

1. a _basic_ value is usually handled by the shim interop
2. an _API_ value is unwrapped from the shim proxy
3. a _json_ (object or array) value is translated from the shim equivalent
4. a _data object_ that provides a deserializer is instantiated from the shim equivalent
5. an _enum_ is converted from a string or an equivalent
6. a _collection_ is usually translated from the shim equivalent
7. a type variable or `java.lang.Object` is converted dynamically converted to a _basic_ type or a _json_ type

=== Argument handlers

Argument handlers have a special treatment as the handlers gets a callback.

Usually a shim creates a `io.vertx.core.Handler<E>` instance whose `handle(E)` implementation
calls back the handler argument applying the return value conversion strategy.

For instance the `HttpClient#getNow` method:

[source,java]
----
void getNow(int port, String host, String requestURI, Handler<HttpClientResponse> responseHandler);
----

Can be translated to

[source,javascript]
----
function(port, host, requestURI, responseHandler) {
  j_httpClient.getNow(port, host, requestURI, function(jVal) {
    responseHandler(new HttpClientResponse(jVal));
  }
}
----

The JavaScript code calling passes a `function(result)`:

[source,javascript]
----
vertx.setTimer(1000, function(id) {
  // Timer fired
});
----

`AsyncResult<R>` types also gets a specific treatment, for instance the `HttpServer#listen` method:

[source,java]
----
void listen(int port, String host, Handler<AsyncResult<HttpServer>> listenHandler);
----

Can be translated to

[source,javascript]
----
function(port, host, listenHandler) {
  j_httpServer.listen(port, host, function(ar) {
    if (ar.succeeded()) {
      listenHandler(new HttpServer(ar.result()), null);
    } else {
      listenHandler(null, ar.cause());
    }
  }
}
----

The JavaScript code calling passes a `function(result, err)`:

[source,javascript]
----
server.listen(80, "localhost", function(result, err) {
  if (result != null) {
    // It worked
  } else {
    // It failed
  }
});
----

=== Argument function

Function arguments are `java.util.function.Function` instances, they are usually mapped to the function
type in the target language or an equivalent.

=== Exceptions

todo

=== Method dispatching

When a shim does not support overloading, it needs to handle the dispatch itself to the Java method, usually
based on the argument types when invocation occurs.

todo provide example ?

== Codegen types

The {@link io.vertx.codegen.type.TypeInfo} provides a codegen view of the Java type system.

A type info has a {@link io.vertx.codegen.type.ClassKind} usually used to determine the conversion to apply:

[cols="1,4"]
.Class kinds
|===
| {@link io.vertx.codegen.type.ClassKind#STRING}
| `java.lang.String`
| {@link io.vertx.codegen.type.ClassKind#PRIMITIVE}
| any Java primitive type
| {@link io.vertx.codegen.type.ClassKind#BOXED_PRIMITIVE}
| any Java boxed primitive type
| {@link io.vertx.codegen.type.ClassKind#ENUM}
| any Java enum
| {@link io.vertx.codegen.type.ClassKind#JSON_OBJECT}
| `io.vertx.core.json.JsonObject`
| {@link io.vertx.codegen.type.ClassKind#JSON_ARRAY}
| `io.vertx.core.json.JsonArray`
| {@link io.vertx.codegen.type.ClassKind#THROWABLE}
| `java.lang.Throwable`
| {@link io.vertx.codegen.type.ClassKind#VOID}
| `java.lang.Void`
| {@link io.vertx.codegen.type.ClassKind#OBJECT}
| `java.lang.Object` or an unbounded type variable
| {@link io.vertx.codegen.type.ClassKind#LIST}
| `java.util.List<V>`
| {@link io.vertx.codegen.type.ClassKind#SET}
| `java.util.Set<V>`
| {@link io.vertx.codegen.type.ClassKind#MAP}
| `java.util.Map<String,V>`
| {@link io.vertx.codegen.type.ClassKind#API}
| any _api_ type
| {@link io.vertx.codegen.type.ClassKind#HANDLER}
| `io.vertx.core.Handler<E>`
| {@link io.vertx.codegen.type.ClassKind#FUNCTION}
| `java.util.function.Function<E, R>`
| {@link io.vertx.codegen.type.ClassKind#ASYNC_RESULT}
| `io.vertx.core.AsyncResult<E>`
| {@link io.vertx.codegen.type.ClassKind#OTHER}
| anything else
|===

The `TypeInfo` base class provides common type information

- {@link io.vertx.codegen.type.TypeInfo#getKind} the type {@link io.vertx.codegen.type.ClassKind}
- {@link io.vertx.codegen.type.TypeInfo#getName()} the type name
- {@link io.vertx.codegen.type.TypeInfo#getSimpleName()} the simple name
- {@link io.vertx.codegen.type.TypeInfo#getErased()} returns the corresponding erased type
- {@link io.vertx.codegen.type.TypeInfo#getRaw()} returns the raw type of a parameter type or this type
- {@link io.vertx.codegen.type.TypeInfo#getDataObject()} returns the data object info this type is associated with

Besides it provides the {@link io.vertx.codegen.type.TypeInfo#translateName(java.lang.String)} method to
translate the type name using a shim identifier, this is useful for shim using a hierarchical naming, for
instance the translated name of `io.vertx.core.eventbus.EventBus` for the `groovy` identifier is
`io.vertx.groovy.core.eventbus.EventBus`. The position where the identifier is applied is
determined by the {@link io.vertx.codegen.annotations.ModuleGen#groupPackage()} value.

Several subclasses of `TypeInfo` provides specialization when needed:

- {@link io.vertx.codegen.type.ClassTypeInfo} : a java class
- {@link io.vertx.codegen.type.ApiTypeInfo} : `TypeInfo.Class` specialization for _api_ types
- {@link io.vertx.codegen.type.EnumTypeInfo} : `TypeInfo.Class` specialization for _enum_ types
- {@link io.vertx.codegen.type.ParameterizedTypeInfo} : a parameterized type
- {@link io.vertx.codegen.type.PrimitiveTypeInfo} : a primitive type
- {@link io.vertx.codegen.type.VoidTypeInfo} : `void` (and not `java.lang.Void`)
- {@link io.vertx.codegen.type.TypeVariableInfo} : an unbounded type variable

The `DataObjectInfo` tells when a type is a data object:

- serializer: the serializer info
- deserializer: the deserializer info

== Codegen models

The codegen processor _validates_ annotated Java program elements (i.e type declaration) and _transforms_  them into models:

1. `ClassModel`
2. `DataObjectModel`
3. `EnumModel`
4. `PackageModel`
5. `ModuleModel`
6. `ProxyModel`

Models are processed by generators. Generators declare which model it wants to process.

For `ClassModel` and `DataObjectModel, annotations on methods/properties can be accessed.

For `ModuleModel`, annotations on package can be accessed. Annotation at type level can be retrieved
for `ClassModel`, `DataObjectModel`, `EnumModel` and `ProxyModel`.

=== Class model

For each Java interface annotated with {@link io.vertx.codegen.annotations.VertxGen} a `{@link io.vertx.codegen.ClassModel}` is created.

[cols="1,4"]
.Template properties
|===
| `importedTypes`
| the full list of used types including `java.lang.*` types as `{@link io.vertx.codegen.type.ClassTypeInfo}` that are not in the same package
| `referencedTypes`
| the full list of used types including `java.lang.*` types as `{@link io.vertx.codegen.type.ClassTypeInfo}`
| `referencedDataObjectTypes`
| the full list of used _data object_ types as `{@link io.vertx.codegen.type.ClassTypeInfo}`
| `type`
| the type `{@link io.vertx.codegen.type.ClassTypeInfo}` or `{@link io.vertx.codegen.type.ParameterizedTypeInfo}`
| `typeParams`
| the list of class type params as `List<`{@link io.vertx.codegen.TypeParamInfo.Class}`>`
| `concrete`
| a boolean value indicating if the model is _abstract_ or _concrete_
| `superTypes`
| all direct super types
| `concreteSuperType`
|the concrete direct super type or null
| `abstractSuperTypes`
| a list of all abstract direct super types
| `handlerSuperType`
| the type `io.vertx.core.Handler<T>` when the type implements directly the `Handler` interface
| `methods`
| all the methods as `List<`{@link io.vertx.codegen.MethodInfo}`>`
| `instanceMethods`
| all the instance methods as `List<`{@link io.vertx.codegen.MethodInfo}`>`
| `staticMethods`
| all the static methods as `List<`{@link io.vertx.codegen.MethodInfo}`>`
| `methodsByName`
| a map of methods keyed by name as `Map<String, List<`{@link io.vertx.codegen.MethodInfo}`>>`
| `doc`
| the documentation as {@link io.vertx.codegen.doc.Doc}
|===

todo method info / param info / type param info

=== Data object model

todo

=== Enum model

todo

=== Package model

todo

=== Module model

todo

=== Proxy model

todo

== Code generation

The {@link io.vertx.codegen.CodeGenProcessor} is a Java Annotation Processor that validates and applies
_code generators_ on codegen models.

The processor is declared in the compiler configuration, here is a typical Maven configuration:

[source,xml]
----
<pluginManagement>
  <plugins>
    <plugin>
      <artifactId>maven-compiler-plugin</artifactId>
      <executions>
        <execution>
          <id>default-testCompile</id>
          <configuration>
            <annotationProcessors>
              <annotationProcessor>io.vertx.codegen.CodeGenProcessor</annotationProcessor>
            </annotationProcessors>
            <compilerArgs>
              <arg>-Acodegen.output=${project.basedir}/src/test</arg> <1>
            </compilerArgs>
          </configuration>
        </execution>
      </executions>
    </plugin>
  </plugins>
</pluginManagement>
----
<1> the base output directory for generated files

Code generators are determined from the classpath by looking at the `META-INF/services/io.vertx.codegen.GeneratorLoader` descriptors.
