/** * = 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 Java class with the only purpose to be a container for data. They are transformed * to and from Json. * * In its simplest form, a data object is a Java class following these rules: * * 1. the class is annotated with {@link io.vertx.codegen.annotations.DataObject} * 2. provide a constructor with the `io.vertx.core.json.JsonObject` argument * * A data object can also be an interface annotated with `@DataObject`, this is useful when multiple inheritance * is needed. For instance Vert.x Core defines the `KeyCertOptions` and `TrustOptions` data object interfaces and the * `JksOptions` is a data object class that implements both of them because a Java keystore provides support for both. * * Data object can also inherit from other data objects. It inherits from the properties of the parent classes. * * ==== Data object properties * * DataObject 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 conversion * * Vert.x requires data object to be convertible from json with the json argument constructor. Altough there * is 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). * * Json 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_ * * ==== Jsonifiable data object * * When a data object declares a `public JsonObject toJson()` method it can be converted to the json format * and is said _jsonifiable_. 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 * * Vert.x requires only the conversion from json, but the conversion to json can be useful when the API uses * data objects as return types. The implementation of the data object / json conversion can be tedious and * error prone. * * The data object / json conversion can be automated based on the rules given above. Vert.x Core allows to * generate auxilliary classes that implement the conversion logic. The generated converters handle 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 type annotated with `io.vertx.codegen.annotations.DataObject` * . _enum_ type : any Java enum * . _collection_ type : `java.util.List<V>`, `java.util.Set<V>` or `java.util.Map<String, V>` * * 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 and _collection_ types. * * Type variables are allowed and carry a special meaning: a type variable is a dynamic form of a _basic_ type and * _json_ type. * * ==== 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 _json_ type * . the `java.lang.Throwable` type * . any _enum_ type * . any _data object_ type that is a non abstract class * . 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. 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 _json_ type * . the `java.lang.Throwable` type - only for `Handler<R>` * . any _enum_ type * . any _data object_ type with a `toJson` method * . 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 * * 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 _json_ type * . the `java.lang.Throwable` type * . any _enum_ type * . any _data object_ type that is a non abstract class * . 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. 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 _json_ type * . the `java.lang.Throwable` type * . any _enum_ type * . any _data object_ type with a `toJson` method * . 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 is a among the method parameter types * * ==== 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. * * ==== 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. * * === 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 jsonifiable _data object_ is converted to 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_ is instantiated from the shim equivalent by its `JsonObject` constructor * 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#DATA_OBJECT} * | any _data object_ 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 * * 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 * * == 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 https://en.wikisource.org/wiki/MVEL_Language_Guide[MVEL] templates, when a template is executed it gets access to implicit properties * (i.e properties that are declared by the model). * * === 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 `codegen.json` descriptors, there can * be several generators executed in the same compilation phase. The configuration of a code generator is * quite simple: * * [source,json] * ---- * { * "name": "Groovy", <1> * "generators": [ { <2> * "kind": "class", <3> * "fileName": "'groovy/' + module.translateQualifiedName(fqn, 'groovy').replace('.', '/') + '.groovy'", <4> * "templateFileName": "vertx-groovy/template/groovy.templ" <5> * } ] * } * ---- * <1> the processor name * <2> an array of generators * <3> the kind of model the generator process : _class_, _dataObject_, _enum_, _package_, _module_, _proxy_ * <4> the MVEL expression of the generated file * <5> the MVEL template file name * * === Templating * * Templates are written in the MVEL language, documented <a href="https://en.wikisource.org/wiki/MVEL_Language_Guide">here</a>. * * Some characters have a special meaning: * * - the tab char is used for formatting purpose and is removed * - the *\n* sequence has the same meaning than in a Java string literal * * === Incremental templating * * Incremental templating allows the same template to process several models and create a single result. This is * useful when several sources files needs to generate a same file and the output is the result of the models. To * achieve incremental processing, a generator must declares `"incremental": true` in its descriptor. * * During the processing phase, the codegen processors collects all the files generated by incremental templates * and groups them by file name. Obviously, the _fileName_ expression of the generator needs to return an appropriate * string. * * At the end of the processing phase, templates are invoked for each model, pretty much like the normal templating but * with the following differences: * * - the variable `incrementalIndex` gives the sequence number of the current model, starting at 0 * - the variable `incrementalSize` gives the total number of models processed by the template * - the variable `session` is a map provided that allows the template to maintain state * - the generated content are appended instead of overwritten * * For instance the template: * * [source] * ---- * @if{incrementalIndex==0} * <html>\n * <body>\n * <ul>\n * @end{} * <li>@{type.name}</li>\n * @if{incrementalIndex==incrementalSize-1} * </ul>\n * </body>\n * </html>\n * @end{} * ---- * * With `codegen.json`: * * [source,json] * ---- * { * "name": "index", * "generators": [ { * "kind": "class", * "incremental": true, * "fileName": "'index.html'", * "templateFileName": "html-index.templ" * } ] * } * ---- * * Generates an HTML page with the name of all the API classes. */ @Document(fileName = "index.adoc") package io.vertx.codegen; import io.vertx.docgen.Document;