Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 9 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,20 @@
[![javadoc](https://javadoc.io/badge2/com.helger/jcodemodel/javadoc.svg)](https://javadoc.io/doc/com.helger/jcodemodel)
<!-- ph-badge-end -->

A fork of the com.sun.codemodel 2.7-SNAPSHOT.
This project provides modeling and exporting java source code at java runtime, either in a pre-processing phase or to access them using a dynamic Classloader.

It is a fork of the com.sun.codemodel 2.7-SNAPSHOT.

The classes in this project use a different package name `com.helger.jcodemodel` to avoid conflicts
with other `com.sun.codemodel` instances that might be floating around in the classpath.
That of course implies, that this artefact cannot directly be used with JAXB, since the configuration of
this would be very tricky.

A site with the links to the [API docs](http://phax.github.io/jcodemodel/) etc. is available.
## Links and doc

- A site with the links to the [API docs](http://phax.github.io/jcodemodel/) etc. is available.
- This project has a dedicated [documentation folder](./docs) maintained by helpers. Don't hesitate [to help](./docs/contributing.md) !


## Maven usage

Expand Down Expand Up @@ -200,28 +207,6 @@ v2.6.4 - 2014-04-10
2013-09-23
* Changes from https://github.com/UnquietCode/JCodeModel have been incorporated.

## Contribution

Pull requests must follow my personal [Coding Styleguide](https://github.com/phax/meta/blob/master/CodingStyleguide.md)

### Tabs vs spaces

This project uses double-space for indentation. If you want to use tabs, you can ask git to modify the files when commiting them and when pulling them. A [specific script](sh/tabspaces) makes that chnage, run it from the root project.


What this script does :

- create the file .git/info/attributes with `*.java filter=tabspace` . This will tell git to apply the script tabspace on the *.java files
- run `git config filter.tabspace.clean 'expand --tabs=2 --initial'` to ask git to replace tabs with two spaces on commit of *.java files.
- run `git config filter.tabspace.smudge 'unexpand --tabs=2 --first-only'` to request git to replace double spaces with two tabs on checking a *.java file out.


### Eclipse

For eclipse, a formatter xml and a cleanup xml are present in the meta/formatter/eclipse/ directory. You can load them from the "project properties > java code style" settings. Check "Enable project specific settings", then load them.

NOTE : you also need to change the save actions to make them meet the clean up actions. Save actions are done even when they are not present in the clean up.



---
Expand Down
81 changes: 81 additions & 0 deletions docs/contributing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
## Contributing

The target audience is people who use JCM already

If you use JCM, you may come across bugs, have ideas to implement, request features that could help you, or help implement or resolve issues.

The ideas and requests should go to the [git's discussion](https://github.com/phax/jcodemodel/discussions) . They can then be converted to issues.

Any bug should go in the [git's issues](https://github.com/phax/jcodemodel/issues) . They are then open for solving. Please provide a minimal working example, so that we can reproduce and check that the verification passes ; also mention what you are working on to avoid multiple person doing the same work.

To help resolve an issue, you can [clone](https://github.com/phax/jcodemodel/fork) the repository, create a new branch, commit your changes, then submit a pull request, explaining what are the choices you made for that issue.

### Formatting

Pull requests must follow my personal [Coding Styleguide](https://github.com/phax/meta/blob/master/CodingStyleguide.md)

#### Tabs vs spaces

This project uses double-space for indentation. If you want to use tabs, you can ask git to modify the files when commiting them and when pulling them. A [specific script](../sh/cfg/tabspaces) makes that change, run it from the root project.


What this script does :

- create the file .git/info/attributes with `*.java filter=tabspace` . This will tell git to apply the script tabspace on the *.java files
- run `git config filter.tabspace.clean 'expand --tabs=2 --initial'` to ask git to replace tabs with two spaces on commit of *.java files.
- run `git config filter.tabspace.smudge 'unexpand --tabs=2 --first-only'` to request git to replace double spaces with tabs when checking a *.java file out.


#### Eclipse

For eclipse, a formatter xml and a cleanup xml are present in the meta/formatter/eclipse/ directory. You can load them from the "project properties > java code style" settings. Check "Enable project specific settings", then load them.

NOTE : you also need to change the save actions to make them meet the clean up actions. Save actions are done even when they are not present in the clean up.


### Testing

New features, as well as bug fixes, are expected to test the minimum amount of use cases to ensure their main usage remains correct.
For example, if you find a bug in a specific case, then that specific case must be tested against in the PR fixing it.
This is important both for validating your PR, but also to ensure new modifications won't break the existing features

Disabling an existing test must be explained (typically no more relevant), at least in the commit or in the PR.

There are three main ways to add tests :
- checking your own class behavior and the generated **file** content,
- checking the generated **class** content and behavior,
- checking your plugin generator behavior.

#### In the main module

You can add usual unit tests in the [main module's test dir](../jcodemodel/src/test/java).

Those are useful to check the behavior of specific parts of the projects, as well as the expected file content for a constructed JCM , typically using [test utils](../jcodemodel/src/test/java/com/helger/jcodemodel/util/CodeModelTestsHelper.java)

Implementation of parsers, validations, a well as code generation that does not persist at runtime (like javadocs, formatting, etc.) are expected to use this method.

Note that the helper class allows to compile a JCM in memory, however using the generated class can be cumbersome since you need to use reflect, unless you can cast it to a known interface.
The next method allows easier manipulation, plus it permits to visually check the generated class files since they are exported and put in git. Therefore any later change in generated files can be tracked down to its commit.

#### In the jcodemodeltests module

[This module](../jcodemodeltests) uses a specific architecture :

1. generating classes should be annotated with `@TestJCM` and contain public methods that have a JCM and/or a JPackage parameter(s), or produce their own JCM. The convention is to end such a class with `TestGen` and place them in their own feature package. The method can be static; if not, a new instance is generated for each generating method.
2. those classes are parsed during the generate-test phase and the resulting (or requested) JCM is then exported in the `src/generated/javatest` dir. You can run the [GenerateTestFiles](../jcodemodeltests/src/main/java/com/helger/jcodemodel/compile/annotation/GenerateTestFiles.java) in your IDE to generate them manually.
3. You can then add test classes in the usual `src/test/java` dir, that rely on those generated classes to check their behaviour and content. The convention is to place the test clas in the same package and with same start as the generating one, ending with `Test`.

General convention is as such, for feature Feat : generat**ing** is `jcodemodel/tests/feat/FeatTestGen.java` ; generat**ed** should be named eg `jcodemodel/tests/feat/FeatExample1.java` ; **testing** class should be `jcodemodel/tests/feat/FeatTest.java`

#### Testing your plugin's generator

A generator generates a JCM that the plugin will export when requested.

- The generator module should be in the [plugin's generators](../plugin/generators/pom.xml) submodule, with a module name starting with `GEN ` (in its pom) ;
- The testing module should be in the [plugins examples](../examples/plugins/pom.xml) submodule, with a module name starting with `XPL Generator ` .

For example, see the [HelloWorld generator](../plugin/generators/helloworld/pom.xml) and its [HelloWorld example](../examples/plugins/helloworld/pom.xml) modules.
The former is *named* `GEN Helloworld`, the later `XPL Generator Helloworld`.

The testing module should not rely on internet data, as this can be an issue when remote host is down.
With [correct configuration](../examples/plugins/helloworld/pom.xml) the plugin will apply the generator and produce the classes in `src/generated/java` , allowing the usual unit tests in that module.
60 changes: 60 additions & 0 deletions docs/extending.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
## Extending JCM with plugin generator

### JCodeModel maven plugin

The plugin is part of the project. However it does not generate data by itself, it needs to be specified a generator. For example, the [helloworld plugin example](../examples/plugins/helloworld/pom.xml) extensively configures that plugin in various ways.

The [plugin](../plugin/plugin/src/main/java/com/helger/jcodemodel/plugin/maven/GenerateSourceMojo.java) does much of the leg-work to load a configured resource, load the configured generator - or default one if none is specified but present as dependency of the plugin - then call that generator and export the produced JCodeModel into a target directory.

It contains several generic settings that can be used when generating the data. For example, the root package of all classes, the target directory, the source to load.
Any more genrator-specific configuration can be passed as the `params` plugin configuration. For example, in the HelloWorld example,

```xml
<configuration>
<generator>com.helger.jcodemodel.plugin.generators.helloworld.HelloWorldGenerator2</generator>
<outputDir>src/generated/java2</outputDir>
<params>
<name>Hello2</name>
<value>world2</value>
</params>
</configuration>
```

forces a specific generator (instead of the default one provided by the HelloWorld Generator) ; then sets the output to be specific one (instead of default `src/generated/java`) ; then transmits the map `name=Hello2, value=world2` to the generator when the plugin is called.

### Creating a generator

To create a new Generator, you must
1. create a new project in the the `plugin/generators` directory
2. add it to the [generators pom](../plugin/generators/pom.xml) modules list
3. create a class that implements `ICodeModelBuilder` and is annotated with `@JCMGen`
4. implement your generator logic in the `void build (JCodeModel model, @Nullable InputStream source) throws JCodeModelException` method.
5. if needed, specify how it's configured by overriding the `void configure (@NonNull final Map <String, String> params)` method

The [annotation processor](../plugin/plugin/src/main/java/com/helger/jcodemodel/plugin/maven/generators/JCMGenProcessor.java) will automatically generate the resources required by the plugin on the maven install phase.

You still need to test your generator, to be sure nothing changes too much

### Testing a generator

Once the generator module is done, you create a new project in the `examples/plugins` module, add it to the [plugin examples](../examples/plugins/pom.xml) modules list, and add your invocation of the plugin, with the generator as its dependency.

This would be something like

```xml
<project>
<build>
<plugins>
<plugin>
<groupId>com.helger.jcodemodel</groupId>
<artifactId>jcodemodel-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>com.helger.jcodemodel.plugin.generators</groupId>
<artifactId>mygenerator</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
```

several executions can be configured, with various generators and/or configurations.
34 changes: 34 additions & 0 deletions docs/overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
## Project overview

### Maven architecture

The project is split in

- The [root pom project](../pom.xml)
- The [core project](../jcodemodel/pom.xml) lib to generate classes and resources programmatically.
- The [test project](../jcodemodeltests/pom.xml) validates the *generated* classes behavior.
- The [plugin](../plugin/plugin/pom.xml) to generate java classes in maven
- The various [plugin generators](../plugin/generators/pom.xml) to load a JCodeModel in the plugin
- The [examples](../examples/pom.xml) that showcase how to use JCodeModel, the plugin, the generators.

### Core classes

#### JCodeModel

This is the main class. It contains the definition of the classes and resources to generate.

Its main usage is to add classes using the various `_class` methods. Those classes can then be added methods, fields, or other classes.

#### JCMWriter

This allows to export a `JCodeModel`. Typically to a directory.

### Scripts

The scripts present in the [sh directory](../sh) are run using a linux shell. For windows, you rather install git for windows which comes with a `bash` shell.

- [cleaninstall](../sh/cleaninstall) runs the maven up-to install phases with parrallel execution and no output of the transfer to reduce logs, with a call to the clean phase to delete all intermediate products. It's only useful when you need to ensure other branches don't interfere with the result, like before a release.
- [install](../sh/install) does it without a clean. That's the main call to typically test changes.
- [mergeupstream](../sh/mergeupstream) adds an `upstream` repository to you local git, if needed, then checks its `master` commits out in the current branch. This allows to have your local branch up-to-date, for example before submitting a PR.
- [upgrades](../sh/upgrades) lists the possible dependencies/plugins upgrades. This is purely informative.
- [voidtest](../sh/voidtest) compiles and run the project, up to the integration-test phase, on a fresh (empty, temporary) maven repository. This will force re-downloading of **all** the libraries and plugins. This is only used when we suspect compiled libraries are generating issues.
Loading