
io.vertx.codegen.package-info Maven / Gradle / Ivy
/**
* = 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 zero argument constructor
* 3. provide a constructor with the `io.vertx.core.json.JsonObject` argument
* 4. provide a copy constructor with the exact same type
*
* 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`/`java.util.Set` or a
* `java.util.Map` where the `` 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 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`
* - `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
* `` 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`, `java.util.Set` or `java.util.Map`
*
* 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
* . 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`, `java.util.Set` or `java.util.Map` where `` 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
*
* In addition callback parameters are allowed, i.e types declaring `io.vertx.core.Handler` or
* `io.vertx.core.Handler>` where `` can be:
*
* . the `java.lang.Void` type
* . any _basic_ type
* . any _API_ type
* . any _json_ type
* . the `java.lang.Throwable` type - only for `Handler`
* . any _enum_ type
* . any _data object_ type
* . 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`, `java.util.Set` or `java.util.Map` where `` 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
* . 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`, `java.util.Set` or `java.util.Map` where `` 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` where T is is a among the method parameter types
* . an `Handler>` 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` 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 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` 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 `` in `` parameter/return, `Handler` or `Handler>` 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 ` void method(GenericApi api)` is not permitted
* . methods can declare nullable collection, e.g `void method(List 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` 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>` 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` wrapping the converted value using the argument value rules,
* otherwise it invokes the handler with the `AsyncResult` 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` 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 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` types also gets a specific treatment, for instance the `HttpServer#listen` method:
*
* [source,java]
* ----
* void listen(int port, String host, Handler> 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
* }
* });
* ----
*
* === 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`
* | {@link io.vertx.codegen.type.ClassKind#SET}
* | `java.util.Set`
* | {@link io.vertx.codegen.type.ClassKind#MAP}
* | `java.util.Map`
* | {@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`
* | {@link io.vertx.codegen.type.ClassKind#ASYNC_RESULT}
* | `io.vertx.core.AsyncResult`
* | {@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` 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>`
* | `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]
* ----
*
*
*
* maven-compiler-plugin
*
*
* default-testCompile
*
*
* io.vertx.codegen.CodeGenProcessor
*
*
* -AoutputDirectory=${project.basedir}/src/test <1>
*
*
*
*
*
*
*
* ----
* <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 here.
*
* 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}
* \n
* \n
* \n
* @end{}
* - @{type.name}
\n
* @if{incrementalIndex==incrementalSize-1}
*
\n
* \n
* \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;
© 2015 - 2025 Weber Informatics LLC | Privacy Policy