Skip to content

Commit

Permalink
initial code upload
Browse files Browse the repository at this point in the history
  • Loading branch information
verhas committed Oct 4, 2018
0 parents commit 0593ffa
Show file tree
Hide file tree
Showing 28 changed files with 809 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*.iml
.idea
pyama
target
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# JavaGeci

Java Generate Code Inline

Javageci is a framework to generate Java code. Code generation programs implemented using Javageci can be executed
to generate new source code, modify existing Java source files. This way the programmer can use meta programming to
express code in a shorter and more expressive way than it would be possible in pure Java.

The framework discovers the files that need generated code, provides easy to use API to generate code and
takes care to write the generated code into the source code. The code generating code should focus on the
actual code structure it wants to generate.

Although many times the need for code generation is a code smell, and is considered to be a bad programming practice
there are valid scenarios where the application of javageci may be okay. These include the followings:

* You could use run-time meta programming (a.k.a. reflection), but the required performance of the application
does not permit the overhead of reflection during run-time. It may also be the case that the debugging of
the reflective utility classes are too complex, but on the other hand the code generated by javageci is
there and is easy to understand and debug.

* You have to use some old version of Java that does not allow advanced functionality and you want to avoid a lot of
boilerplate code.


15 changes: 15 additions & 0 deletions annotation/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>com.javax0.geci</groupId>
<artifactId>multi</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>

<artifactId>annotation</artifactId>
<name>geci annotation</name>
<packaging>jar</packaging>
</project>
11 changes: 11 additions & 0 deletions annotation/src/main/java/javax0/geci/annotations/Geci.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package javax0.geci.annotations;

import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Gecis.class)
public @interface Geci {
String value() default "";
}
9 changes: 9 additions & 0 deletions annotation/src/main/java/javax0/geci/annotations/Gecis.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package javax0.geci.annotations;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface Gecis {
Geci[] value();
}
3 changes: 3 additions & 0 deletions annotation/src/main/java/module-info.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module geci.annotation {
exports javax0.geci.annotations;
}
15 changes: 15 additions & 0 deletions api/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>com.javax0.geci</groupId>
<artifactId>multi</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>

<artifactId>api</artifactId>
<name>geci api</name>
<packaging>jar</packaging>
</project>
31 changes: 31 additions & 0 deletions api/src/main/java/javax0/geci/api/Geci.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package javax0.geci.api;

import java.io.IOException;

public interface Geci {

/**
* Add a new directory to the list of source directories that Geci should process.
*
* @param directory
* @return {@code this}
*/
Geci source(String directory);

/**
* Register a generator instance.
*
* @param generator the generator to register
* @return {@code this}
*/
Geci register(Generator generator);

/**
* Run the code generation.
* @return {@code false} if the code generation did not produce any output. It means that the code was
* already up to date. {@code true} when code was generated. When the code generation is executed
* as a unit test this return value can be asserted and compilation may fail in case code was changed.
*/
boolean generate() throws Exception;

}
10 changes: 10 additions & 0 deletions api/src/main/java/javax0/geci/api/Generator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package javax0.geci.api;

/**
* Generators get source code information from the framework and generate code. File writing and inserting the
* code to the existing source code and mixing the manual and generated code is up to the framework.
*/
public interface Generator {

void process(Source source);
}
7 changes: 7 additions & 0 deletions api/src/main/java/javax0/geci/api/Segment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package javax0.geci.api;

public interface Segment {
void write(String s);
void write_r(String s);
void write_l(String s);
}
17 changes: 17 additions & 0 deletions api/src/main/java/javax0/geci/api/Source.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package javax0.geci.api;

import java.io.IOException;

public interface Source {
/**
* Return the named segment that the generator can write. Return {@code null} if there is no such segment
* in the file.
*
* @param id the name of the segment as defined in the {@code id="..."} xml tag of the {@code <editor-fold ...>}
* @return the segment or {@code null}.
* @throws IOException
*/
Segment open(String id) throws IOException;

String file();
}
3 changes: 3 additions & 0 deletions api/src/main/java/module-info.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module geci.api {
exports javax0.geci.api;
}
37 changes: 37 additions & 0 deletions core/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>com.javax0.geci</groupId>
<artifactId>multi</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>

<artifactId>core</artifactId>
<name>geci core</name>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>com.javax0.geci</groupId>
<artifactId>api</artifactId>
</dependency>
<dependency>
<groupId>com.javax0.geci</groupId>
<artifactId>tools</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
</dependency>
</dependencies>

</project>
37 changes: 37 additions & 0 deletions core/src/main/java/javax0/geci/delegator/Delegate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package javax0.geci.delegator;

import javax0.geci.api.Generator;
import javax0.geci.api.Source;
import javax0.geci.tools.Tools;

public class Delegate implements Generator {
@Override
public void process(Source source) {
try {
process0(source);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

private void process0(Source source) throws Exception {
final Class klass;
klass = Tools.getClass(source);
var fields = klass.getDeclaredFields();
for (var field : fields) {
var params = Tools.getParameters(field, "delegate");
if (!params.containsKey("id")) {
throw new RuntimeException("Field " + field + " in class " + klass + " has no 'id' in annotation Geci");
}
var id = params.get("id");
var segment = source.open(id);
var delClass = field.getType();
var methods = delClass.getMethods();
var name = field.getName();
for( var method : methods ){
segment.write_r(""+method.getModifiers()+" "+method.getName()+"(){");
segment.write_l("}");
}
}
}
}
4 changes: 4 additions & 0 deletions core/src/main/java/module-info.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module geci.core {
requires geci.api;
requires geci.tools;
}
11 changes: 11 additions & 0 deletions core/src/test/java/javax0/geci/delegator/TestDelegator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package javax0.geci.delegator;

import org.junit.jupiter.api.Test;

public class TestDelegator {

@Test
public void testDelegator(){

}
}
53 changes: 53 additions & 0 deletions engine/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
</build>

<parent>
<groupId>com.javax0.geci</groupId>
<artifactId>multi</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>

<artifactId>engine</artifactId>
<name>geci engine</name>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>com.javax0.geci</groupId>
<artifactId>api</artifactId>
</dependency>
<dependency>
<groupId>com.javax0.geci</groupId>
<artifactId>tools</artifactId>
</dependency>
<dependency>
<groupId>com.javax0.geci</groupId>
<artifactId>core</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
</dependency>
</dependencies>

</project>
44 changes: 44 additions & 0 deletions engine/src/main/java/javax0/geci/engine/Geci.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package javax0.geci.engine;

import javax0.geci.api.Generator;
import javax0.geci.util.FileCollector;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Geci implements javax0.geci.api.Geci {

private final Set<String> directories = new HashSet<>();
private final List<Generator> generators = new ArrayList<>();

@Override
public javax0.geci.api.Geci source(String directory) {
directories.add(directory);
return this;
}

@Override
public javax0.geci.api.Geci register(Generator generator) {
generators.add(generator);
return this;
}

@Override
public boolean generate() throws IOException {
var sources = new FileCollector(directories).collect();
for (var source : sources) {
for (var generator : generators) {
generator.process(source);
}
}
for (var source : sources) {
source.consolidate();
source.save();
}

return false;
}
}
29 changes: 29 additions & 0 deletions engine/src/main/java/javax0/geci/engine/Segment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package javax0.geci.engine;

import java.util.LinkedList;
import java.util.List;

public class Segment implements javax0.geci.api.Segment {
final List<String> lines = new LinkedList<>();
int tabStop = 0;

@Override
public void write(String s) {
lines.add(" ".repeat(tabStop) + s);
}

@Override
public void write_r(String s) {
write(s);
tabStop += 4;
}

@Override
public void write_l(String s) {
write(s);
tabStop -= 4;
if (tabStop < 0) {
tabStop = 0;
}
}
}
Loading

0 comments on commit 0593ffa

Please sign in to comment.