I got some automatically generated Java code. I am willing to refactor automatically before compiling. It is mostly class rename and package modification.
Are there any gradle or ant tasks available for this?
I got some automatically generated Java code. I am willing to refactor automatically before compiling. It is mostly class rename and package modification.
Are there any gradle or ant tasks available for this?
I got some automatically generated java code I would like to automaticaly refactor before compiling it. It is mostly class rename and package modification.
[off topic comment: You should fix the code that generate the code. Generating code automatically and then modify it using another tool does not look like correct approach.]
Eclipse provides refactoring API that can be used in programs(without eclipse). Original tool was JDT(I had used it), I guess the new solution is LTK - not tried.
What you want is a program transformation system (PTS).
A PTS reads source code, builds a program representation (usually an abstract syntax tree or AST), applies transformations (often stated in "if you see this, replace it by that" target langauge "surface" syntax) to the tree, and can regenerate valid source text (often prettyprinted) from the modified AST. An example surface syntax might be written literally as follows (syntax varies per system):
\x ** 2 ==> \x * \x
Usually a set of transformation rules working in cooperation, controlled by a metaprogram, are needed to achieve a more complex result. How metaprograms are written vary radically across the PTS.
You generally have to configure the PTS to parse/prettyprint the target language of choice. Stratego, TXL, and DMS (my tool) all have Java parsers/prettyprinters already and all have surface syntax rewrites. Given the choice of PTS, you would generate your source code, then launch a process to run the tool, using a set of transformations and corresponding metaprogram that you provide to achieve the specific code changes you want. Stratego, I believe, has a Java implementation, and you might be able to integrate it into your application, avoiding the separate process.
A complication is that often the transformations you want to do, require name resolution, type information, or some understanding of dataflow in the code. Stratego and TXL do not have this information built in, so you have to compute it on demand by writing additional transformations; that's actually a little hard because the language semantics are complex. Our tool, DMS, has these facilities already complete for Java with some incompleteness on the data flow.
If your problem is really just name substitution, and the names are unique in your generated code, then you might get away with transformations like:
uniquename1 ==> replacementpath1
e.g.
foo.bar ==> baz.bar.foo
(If this is really enough, you might get away with just text string substitution rather than a PTS. Most of my career has been spent discovering that nothing is ever as simple as I had hoped).
Eclipse's JDT might be an alternative. It certainly has a parser, but no surface syntax transformations so it isn't really a PTS). Instead transformations are coded in Java by walking up and down the tree and making changes using JDT APIs, so it is a bit painful. AFAIK, it provides access to name information but not expression types if I understand it, and has no specific support for data flow. I understand it isn't easy to isolate it from Eclipse for use as a module; YMMV.
There used to be a standalone tool called Spoon, that provided Java parsing, full name and type resolution, but has on procedural tree modifications. I don't know if has tracked modern dialects of Java (e.g., 1.5 and up with templates).
as you said you use "xjc" to generate the code and you want "mostly class rename and package modification" maybe some of the "xjc" options would do what you want:
-p <pkg> : specifies the target package
-b <file/dir> : specify external bindings files (each <file> must have its own -b)
If a directory is given, **/*.xjb is searched
With "-p" you can define the target package to which the generated code should belong. For using the bindings option have a look here for further information http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/2.0/tutorial/doc/JAXBUsing4.html
edit Another approach could be: to move the generated files in the directory you want and then using the replace plugin to replace the package specification in the copied source files
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>the.directory.for.the.classes.to.move.to</outputDirectory>
<resources>
<resource>
<directory>the.directory.of.ajc.classes</directory>
... do here the appropriate settings ...
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>1.5.2</version>
<executions>
<execution>
<phase>process-sources</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<includes>
<include>**/src/main/gen/**/**.java</include>
</includes>
<token>^package the.one.you.want.to.replace</token>
<value>package you.want.the.classes.to.be</value>
<regexFlags>
<regexFlag>MULTILINE</regexFlag>
</regexFlags>
</configuration>
</plugin>
If you're trying to control the package and class names generated by xjc you can provide an external binding file.
You would say something like:
<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<jxb:bindings schemaLocation="your.xsd" node="/xs:schema">
<jxb:schemaBindings>
<jxb:package name="the.package.name.you.want" />
</jxb:schemaBindings>
</jxb:bindings>
</jxb:bindings>
And for each class name you want to customize you would have:
<jxb:bindings node="//xs:complexType[@name='UglyTypeName']">
<jxb:class name="MyNiceClass"/>
</jxb:bindings>
Save this up into a bindings.xjb
file, for example, and run xjc like so:
xjc your.xsd -b bindings.xjb
There is a tools named Spoon. This project is open source and enables you to transform and analyze Java source code with an approach source-to-source. It provides a complete and fine-grained Java metamodel where any program element (classes, methods, fields, statements, expressions...) can be accessed both for reading and modification.
You can have more information about it on its website: http://spoon.gforge.inria.fr/.
To run spoon with Gradle, there is plugin that you can insert on your project and apply Spoon on it. To use it, clone this project (https://github.com/SpoonLabs/spoon-gradle-plugin) and install the plugin on your local repository (./gradlew install
). After, you can insert it on your project how is explained in the documentation of the plugin (https://github.com/SpoonLabs/spoon-gradle-plugin#basic-usage).
I hope this can help any new developer interested in the java transformation source to source! :)
You can do it after compiling with proguard. There is a gradle task for proguard.