Skip to content

Commit 1d0dd29

Browse files
committed
First simple working version that generates 20002 random files
- classes and interfaces - uses random java classes / imports from different modules - uses generics - random cross-referencing
1 parent 2e76a2e commit 1d0dd29

File tree

7 files changed

+377
-1
lines changed

7 files changed

+377
-1
lines changed

JavaProjectGenerator/.classpath

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
<classpath>
33
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
44
<classpathentry kind="src" path="src"/>
5+
<classpathentry kind="src" path="target/generated"/>
56
<classpathentry kind="output" path="bin"/>
67
</classpath>
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package de.loskutov.jpg;
2+
3+
public class Clazz extends JavaElement {
4+
5+
String implement;
6+
String extend;
7+
8+
Clazz(String name, String packageName, String implement, String extend) {
9+
super(name, packageName);
10+
this.implement = implement;
11+
this.extend = extend;
12+
}
13+
14+
@Override
15+
String generateCode() {
16+
boolean object = "java.lang.Object".equals(extend);
17+
if(object) {
18+
return generateObject();
19+
}
20+
String s = "package " + packageName + ";\n\n" +
21+
"import " + imports.next() + ";\n\n" +
22+
"@SuppressWarnings(\"all\")\n" +
23+
"public abstract class " + name + "<E> extends " + extend + "<E> implements " + implement + "<E> {\n\n" +
24+
"\t public E element;\n\n" +
25+
"\t public " + fields.next() + " field1;\n\n" +
26+
"\t public static " + name + " instance;\n\n" +
27+
"\t public static " + name + " getInstance() {\n" +
28+
"\t \t return instance;\n" +
29+
"\t }\n\n" +
30+
"\t public static <T> T create(java.util.List<T> input) {\n" +
31+
"\t \t return " + extend + ".create(input);\n" +
32+
"\t }\n\n" +
33+
"\t public String getName() {\n" +
34+
"\t \t return " + extend + ".getInstance().getName();\n" +
35+
"\t }\n\n" +
36+
"\t public void setName(String string) {\n" +
37+
"\t \t " + extend + ".getInstance().setName(getName());\n" +
38+
"\t \t return;\n" +
39+
"\t }\n\n" +
40+
"\t public E get() {\n" +
41+
"\t \t return (E)" + extend + ".getInstance().get();\n" +
42+
"\t }\n\n" +
43+
"\t public void set(Object element) {\n" +
44+
"\t \t this.element = (E)element;\n" +
45+
"\t \t " + extend + ".getInstance().set(this.element);\n" +
46+
"\t }\n\n" +
47+
"\t public E call() throws Exception {\n" +
48+
"\t \t return (E)" + extend + ".getInstance().call();\n" +
49+
"\t }\n" +
50+
"}\n";
51+
return s;
52+
}
53+
54+
String generateObject() {
55+
String s = "package " + packageName + ";\n" +
56+
"import " + imports.next() + ";\n" +
57+
"@SuppressWarnings(\"all\")\n" +
58+
"public abstract class " + name + "<E> implements " + implement + "<E> {\n" +
59+
"public E element;\n" +
60+
"public " + fields.next() + " field1;\n" +
61+
"public static " + name + " instance;\n" +
62+
"public static " + name + " getInstance() {\n" +
63+
"\t return instance;\n" +
64+
"}\n" +
65+
66+
"public static <T> T create(java.util.List<T> input) {\n" +
67+
"\t return null;\n" +
68+
"}\n" +
69+
70+
"public String getName() {\n" +
71+
"\t return element.toString();\n" +
72+
"}\n" +
73+
74+
"public void setName(String string) {\n" +
75+
"\t return;\n" +
76+
"}\n" +
77+
78+
"public E get() {\n" +
79+
"\t return element;\n" +
80+
"}\n" +
81+
82+
"public void set(Object element) {\n" +
83+
"\t this.element = (E)element;\n" +
84+
"}\n" +
85+
86+
"public E call() throws Exception {\n" +
87+
"\t return (E)getInstance().call();\n" +
88+
"}\n" +
89+
"}\n";
90+
return s;
91+
}
92+
93+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package de.loskutov.jpg;
2+
3+
public class Interface extends JavaElement {
4+
5+
private String extend;
6+
7+
Interface(String name, String packageName, String extend) {
8+
super(name, packageName);
9+
this.extend = extend;
10+
}
11+
12+
@Override
13+
String generateCode() {
14+
String s = "package " + packageName + ";\n\n" +
15+
"import " + imports.next() + ";\n\n" +
16+
"@SuppressWarnings(\"all\")\n" +
17+
"public interface " + name + "<E> extends " + extend + "<E> {\n\n" +
18+
19+
"\t " + fields.next() + " ifield = null;\n\n" +
20+
21+
"\t String getName();\n\n" +
22+
23+
"\t void setName(String s);\n\n" +
24+
25+
"\t E get();\n\n" +
26+
27+
"\t void set(E e);\n\n" +
28+
"}\n";
29+
return s;
30+
}
31+
32+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package de.loskutov.jpg;
2+
3+
import java.io.BufferedWriter;
4+
import java.io.File;
5+
import java.io.IOException;
6+
import java.nio.charset.StandardCharsets;
7+
import java.nio.file.Files;
8+
import java.nio.file.Path;
9+
import java.util.Arrays;
10+
import java.util.List;
11+
12+
public abstract class JavaElement {
13+
14+
static final List<String> IMPORTS = Arrays.asList(
15+
"java.awt.datatransfer.*",
16+
"java.beans.beancontext.*",
17+
"java.io.*",
18+
"java.rmi.*",
19+
"java.nio.file.*",
20+
"java.sql.*",
21+
"java.util.logging.*",
22+
"java.util.zip.*",
23+
"javax.annotation.processing.*",
24+
"javax.lang.model.*",
25+
"javax.management.*",
26+
"javax.naming.directory.*",
27+
"javax.net.ssl.*",
28+
"javax.rmi.ssl.*"
29+
);
30+
31+
static final List<String> FIELDS = Arrays.asList(
32+
"java.awt.datatransfer.DataFlavor",
33+
"java.beans.beancontext.BeanContext",
34+
"java.io.File",
35+
"java.rmi.Remote",
36+
"java.nio.file.FileStore",
37+
"java.sql.Array",
38+
"java.util.logging.Filter",
39+
"java.util.zip.Deflater",
40+
"javax.annotation.processing.Completion",
41+
"javax.lang.model.AnnotatedConstruct",
42+
"javax.management.Attribute",
43+
"javax.naming.directory.DirContext",
44+
"javax.net.ssl.ExtendedSSLSession",
45+
"javax.rmi.ssl.SslRMIClientSocketFactory"
46+
);
47+
48+
String name;
49+
String packageName;
50+
Ring<String> imports;
51+
Ring<String> fields;
52+
53+
JavaElement(String name, String packageName){
54+
this.name = name;
55+
this.packageName = packageName;
56+
imports = new Ring<>(IMPORTS);
57+
fields = new Ring<>(FIELDS);
58+
}
59+
60+
abstract String generateCode();
61+
62+
void persist(Path root) throws IOException {
63+
try(BufferedWriter writer = createWriter(root)){
64+
String code = generateCode();
65+
writer.append(code);
66+
writer.flush();
67+
}
68+
}
69+
70+
String fqn() {
71+
return packageName + "." + name;
72+
}
73+
74+
BufferedWriter createWriter(Path root) throws IOException {
75+
Path path = root.resolve(packageName.replace('.', File.separatorChar)).resolve(name + ".java");
76+
Files.createDirectories(path.getParent());
77+
return Files.newBufferedWriter(path, StandardCharsets.UTF_8);
78+
}
79+
}
Lines changed: 118 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,126 @@
11
package de.loskutov.jpg;
22

3+
import java.io.File;
4+
import java.io.IOException;
5+
import java.nio.file.FileVisitResult;
6+
import java.nio.file.Files;
7+
import java.nio.file.Path;
8+
import java.nio.file.SimpleFileVisitor;
9+
import java.nio.file.attribute.BasicFileAttributes;
10+
import java.util.ArrayList;
11+
import java.util.List;
12+
import java.util.stream.Collectors;
13+
import java.util.stream.IntStream;
14+
import java.util.stream.Stream;
15+
316
public class Main {
17+
18+
public static void main(String[] args) throws IOException {
19+
File rootDir = new File("./target/generated/");
20+
System.out.println("Writing to " + rootDir.getAbsolutePath());
21+
Path root = rootDir.toPath();
22+
23+
24+
int depth = 10;
25+
int roots = 10;
26+
int classes = 100;
27+
28+
new JavaBuilder(depth, roots, classes, root).build();
29+
}
30+
}
31+
32+
class JavaBuilder {
33+
34+
static List<String> namesList = IntStream.rangeClosed('a', 'z').mapToObj(x -> String.valueOf((char)x))
35+
.collect(Collectors.toList());
36+
37+
int depth;
38+
int roots;
39+
private Ring<String> pnames;
40+
private Path root;
41+
42+
private List<Clazz> classes;
443

5-
public static void main(String[] args) {
44+
private List<Interface> interfaces;
45+
46+
private int countClasses;
47+
48+
public JavaBuilder(int depth, int roots, int countClasses, Path root) {
49+
this.depth = depth;
50+
this.roots = roots;
51+
this.countClasses = countClasses;
52+
this.root = root;
53+
pnames = new Ring<>(namesList);
54+
classes = new ArrayList<>();
55+
interfaces = new ArrayList<>();
56+
}
57+
58+
void build() throws IOException {
59+
Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
60+
@Override
61+
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
62+
Files.delete(file);
63+
return FileVisitResult.CONTINUE;
64+
}
65+
66+
@Override
67+
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
68+
Files.delete(dir);
69+
return FileVisitResult.CONTINUE;
70+
}
71+
});
72+
Files.createDirectories(root);
73+
74+
List<Package> rootPackages = new ArrayList<>();
75+
for (int i = 0; i < roots; i++) {
76+
Package p = createPackage(pnames.next(), null);
77+
rootPackages.add(p);
78+
}
679

80+
for (Package r : rootPackages) {
81+
Stream<Package> stream = Stream.iterate(r, x -> new Package(pnames.next(), x)).limit(depth);
82+
stream.forEach(p -> {
83+
createInterfaces(p);
84+
createClasses(p);
85+
});
86+
}
87+
List<JavaElement> elements = new ArrayList<>(interfaces);
88+
elements.addAll(classes);
89+
elements.forEach(this::generateFile);
90+
System.out.println("Generated " + elements.size() + " classes");
791
}
892

93+
private void generateFile(JavaElement e) {
94+
try {
95+
e.persist(root);
96+
} catch (IOException e1) {
97+
e1.printStackTrace();
98+
}
99+
}
100+
101+
void createInterfaces(Package p) {
102+
Ring<Interface> toImplement = new Ring<>(interfaces, countClasses);
103+
if(interfaces.isEmpty()) {
104+
interfaces.add(new Interface("IFoo0", p.getFqn(), "java.util.concurrent.Callable"));
105+
}
106+
toImplement.stream().forEach(i -> {
107+
interfaces.add(new Interface("IFoo" + interfaces.size(), p.getFqn(), toImplement.next().fqn()));
108+
});
109+
}
110+
111+
void createClasses(Package p) {
112+
Ring<Interface> implement = new Ring<>(interfaces, countClasses);
113+
Ring<Clazz> toExtend = new Ring<>(classes, countClasses);
114+
if (classes.isEmpty()) {
115+
classes.add(new Clazz("Element0", p.getFqn(), implement.next().fqn(), "java.lang.Object"));
116+
}
117+
toExtend.stream().forEach(x -> {
118+
classes.add(new Clazz("Element" + classes.size(), p.getFqn(), implement.next().fqn(), toExtend.next().fqn()));
119+
});
120+
}
121+
122+
Package createPackage(String name, Package parent) {
123+
return new Package(name, parent);
124+
}
125+
9126
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package de.loskutov.jpg;
2+
3+
public class Package {
4+
private String fqn;
5+
6+
Package(String name, Package parent){
7+
this.fqn = parent == null? name : parent.fqn + "." + name;
8+
}
9+
10+
public String getFqn() {
11+
return fqn;
12+
}
13+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package de.loskutov.jpg;
2+
3+
import java.util.ArrayList;
4+
import java.util.Collections;
5+
import java.util.List;
6+
import java.util.stream.Stream;
7+
8+
public class Ring<E> {
9+
private List<E> choices;
10+
int cursor = -1;
11+
private int limit;
12+
13+
Ring(List<E> list){
14+
this(list, -1);
15+
}
16+
17+
Ring(List<E> list, int limit){
18+
this.limit = limit;
19+
if(list instanceof ArrayList) {
20+
this.choices = list;
21+
} else {
22+
this.choices = new ArrayList<>(list);
23+
}
24+
Collections.shuffle(choices);
25+
}
26+
27+
E next() {
28+
cursor ++;
29+
if(cursor >= choices.size()) {
30+
cursor = 0;
31+
}
32+
return choices.get(cursor);
33+
}
34+
35+
Stream<E> stream(){
36+
if(limit > 0) {
37+
return Stream.generate(() -> next()).limit(limit);
38+
}
39+
return Stream.generate(() -> next());
40+
}
41+
}

0 commit comments

Comments
 (0)