Providence CLI Tool : Code Generator

The code generator (called compiler in Apache Thrift) pvdgen, this can be used in place of the maven plugin for non-java projects. Out of the box, it can generate files for:

  • json: Simply writes out the thrift definitions as JSON files, one file per thrift or providence IDL file. Note that acceptance differences between .thrift and .providence files are not propagated through to these files, but they should not pass unless accepted anyway.
  • java: Writes the standard providence java generated code. See the generator help for detailed instructions.

See pvdgen --help for more detailed info about the available options.

Developing Generator Modules

See providence-js for an example of how to add a simple external generator. Note that because of the tie-in with the contained descriptions and the type registries the generators may be pretty dependent on the providence version installed.

Creating a generator.

First you need to extend the Generator class, which does the actual code generating. The generate method is given a ProgramTypeRegistry which represents a single thrift program file, and references all it's dependencies. The generateGlobal is only called once, and can be used to generate "global" config or other files, e.g. like the JS generator may need to include some "system" JS files.

public class MyGenerator extends Generator {
    private final GeneratorOptions         generatorOptions;
    private final MyOptions                options;

    public MyGenerator(FileManager manager, GeneratorOptions generatorOptions, MyOptions jsOptions) throws GeneratorException {
        super(manager);

        this.options = jsOptions;
        this.generatorOptions = generatorOptions;
    }

    @Override
    @SuppressWarnings("resource")
    public void generate(ProgramRegistry registry) throws IOException, GeneratorException {
        CProgram program = registry.getProgram();
        // generate file or files bassed on this program.
    }

    @Override
    public void generateGlobal(GlobalRegistry registry,
                               Collection<File> inputFiles) throws IOException, GeneratorException {
        boolean service = false;
        for (ProgramTypeRegistry reg : registry.getLoadedRegistries()) {
            CProgram program = reg.getProgram();
            if (program.getServices().size() > 0) {
                service = true;
                break;
            }
        }

        if (service) {
            // add service files.
        }
    }
}

Creating Generator Factory

Second you need to implement the GeneratorFactory for the generator. This class is used to find the actual generator (for pvdgen) and to make a generator instance, parse options etc.

public class MyGeneratorFactory implements GeneratorFactory {
    @Override
    public String generatorName() {
        return "my";
    }

    @Override
    public String generatorDescription() {
        return "Generates my stuff";
    }

    @Override
    public void printGeneratorOptionsHelp(PrintStream out) {
        System.out.println(" - name    : My option.");
    }

    private JSOptions makeMyOptions(Collection<String> optionNames) {
        MyOptions options = new MyOptions();
        for (String opt : optionNames) {
            switch (opt) {
                case "name":
                    options.name = true;
                    break;
                default:
                    throw new RuntimeException("No such option for my generator: " + opt);
            }
        }
        options.validate();
        return options;
    }

    @Override
    public Generator createGenerator(FileManager manager,
                                     GeneratorOptions generatorOptions,
                                     Collection<String> options) {
        return new MyGenerator(manager, generatorOptions, makeMyOptions(options));
    }
}

Building a Jar

Then you need to make a jar file for the generator. This needs to have the Providence-Generator-Factory property in the manifest, which must point to the factory class implemented above.

Packaging

In order to have pvdgen pick up the generator, you can do one of the following.

  • Add jar file absolute path to generator_paths in one of:
    • ${HOME}/.pvdrc (pretty / providence config format, for user testing)
    • /etc/providence/*.json (json, for native installs)
    • /usr/local/etc/providence/*.json (json, for homebrew on mac)
    • /${HOME}/.linuxbrew/etc/providence/*.json (json, for linuxbrew)
  • Place the jar file in the generator directory under ${PREFIX}/share/providence/generator e.g. like this: /usr/local/share/providence/generator/my.jar.

Example config files:

config.ProvidenceTools {
    generator_paths = [
        "/path/to/my.jar"
    ]
}
{
    "generator_paths": [
        "/path/to/my.jar"
    ]
}