org.babyfish.jimmer.client.generator.CodeWriter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jimmer-client Show documentation
Show all versions of jimmer-client Show documentation
A revolutionary ORM framework for both java and kotlin
package org.babyfish.jimmer.client.generator;
import org.babyfish.jimmer.client.meta.*;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public abstract class CodeWriter {
protected final C ctx;
protected final File file;
private final StringBuilder codeBuilder = new StringBuilder();
private int indent;
private boolean lineDirty;
private Scope scope;
protected CodeWriter(C ctx, File file) {
this.ctx = ctx;
this.file = file;
}
public final C getContext() {
return ctx;
}
public final File getFile() {
return file;
}
public final CodeWriter codeIf(boolean cond, String ts) {
if (cond) {
return code(ts);
}
return this;
}
public final CodeWriter codeIf(boolean cond, char c) {
if (cond) {
return code(c);
}
return this;
}
public final CodeWriter code(String ts) {
if (ts.isEmpty()) {
return this;
}
int size = ts.length();
for (int i = 0; i < size; i++) {
doAdd(ts.charAt(i));
}
return this;
}
public final CodeWriter code(char c) {
doAdd(c);
return this;
}
public final CodeWriter importFile(File file) {
return importFile(file, false, null);
}
public final CodeWriter importFile(File file, List nestedNames) {
return importFile(file, false, nestedNames);
}
public final CodeWriter importFile(File file, boolean treatAsData) {
return importFile(file, treatAsData, null);
}
public final CodeWriter importFile(File file, boolean treatAsData, List nestedNames) {
if (file != null && !file.equals(this.file)) {
onImport(file, treatAsData, nestedNames);
}
return this;
}
protected abstract void onImport(File file, boolean treatAsData, List nestedNames);
public final CodeWriter typeRef(Type type) {
return typeRef(type, null);
}
public final CodeWriter typeRef(Type type, List nestedNames) {
if (type instanceof UnresolvedTypeVariable) {
code(((UnresolvedTypeVariable)type).getName());
} else if (type instanceof SimpleType) {
writeSimpleTypeRef((SimpleType) type);
} else if (type instanceof NullableType) {
writeNullableTypeRef((NullableType) type);
} else if (type instanceof ArrayType) {
writeArrayTypeRef((ArrayType) type);
} else if (type instanceof MapType) {
writeMapTypeRef((MapType) type);
} else {
File file = ctx.getFile(type);
if (file != null) {
importFile(file, nestedNames);
if (type instanceof ImmutableObjectType &&
rawImmutableAsDynamic() &&
((ImmutableObjectType)type).getCategory() == ImmutableObjectType.Category.RAW) {
writeDynamicTypeRef((ImmutableObjectType) type);
} else if (type instanceof StaticObjectType) {
writeStaticTypeRef((StaticObjectType) type);
} else {
code(file.getName());
}
} else if (type instanceof ImmutableObjectType) {
writeDtoTypeRef((ImmutableObjectType) type);
} else if (type instanceof StaticObjectType && (nestedNames == null || nestedNames.isEmpty())) {
StaticObjectType staticObjectType = (StaticObjectType) type;
List simpleNames = new ArrayList<>();
while (staticObjectType.getDeclaringObjectType() != null) {
simpleNames.add(staticObjectType.getJavaType().getSimpleName());
staticObjectType = staticObjectType.getDeclaringObjectType();
}
if (!simpleNames.isEmpty()) {
Collections.reverse(simpleNames);
return typeRef(staticObjectType, simpleNames);
}
}
}
if (nestedNames != null) {
String sp = ctx.nestedTypeSeparator();
for (String nestedName : nestedNames) {
code(sp).code(nestedName);
}
}
return this;
}
public CodeWriter separator() {
Scope scope = this.scope;
if (scope == null) {
throw new IllegalStateException("There is no existing scope");
}
if (scope.dirty) {
code(scope.separator);
if (scope.multiLines) {
code('\n');
}
}
return this;
}
public CodeWriter document(Document document) {
if (document == null) {
return null;
}
boolean visitedFirstLine = false;
code("/**\n");
for (Document.Item item : document.getItems()) {
code(" * ");
if (item.getDepth() != 0) {
for (int i = item.getDepth(); i > 1; --i) {
code(ctx.getIndent());
}
code('-').code(ctx.getIndent().substring(1));
} else {
if (visitedFirstLine) {
code("\n * ");
}
}
code(item.getText());
code('\n');
visitedFirstLine = true;
}
code(" */\n");
return this;
}
private void doAdd(char c) {
if (!lineDirty) {
for (int i = indent; i > 0; --i) {
codeBuilder.append(ctx.getIndent());
}
lineDirty = true;
}
if (scope != null) {
scope.dirty();
}
codeBuilder.append(c);
if (c == '\n') {
lineDirty = false;
}
}
public CodeWriter scope(ScopeType type, String separator, boolean multiLines, Runnable runnable) {
Scope oldScope = scope;
Scope newScope = new Scope(oldScope, separator, multiLines);
code(type.prefix);
if (multiLines) {
code('\n');
indent++;
}
scope = newScope;
runnable.run();
if (multiLines) {
--indent;
if (lineDirty) {
code('\n');
}
}
code(type.suffix);
scope = oldScope;
return this;
}
protected abstract void write();
public final void flush() throws IOException {
OutputStreamWriter writer = new OutputStreamWriter(ctx.getOutputStream());
write();
writePackageHeader(writer);
writeImportHeader(writer);
writer.write(codeBuilder.toString());
writer.flush();
}
protected void writePackageHeader(Writer writer) throws IOException {}
protected abstract void writeImportHeader(Writer writer) throws IOException;
protected boolean rawImmutableAsDynamic() {
return false;
}
protected abstract void writeSimpleTypeRef(SimpleType simpleType);
protected abstract void writeNullableTypeRef(NullableType nullableType);
protected abstract void writeArrayTypeRef(ArrayType arrayType);
protected abstract void writeMapTypeRef(MapType mapType);
protected abstract void writeDynamicTypeRef(ImmutableObjectType type);
protected void writeStaticTypeRef(StaticObjectType type) {
code(getContext().getFile(type).getName());
List typeArguments = type.getTypeArguments();
if (!typeArguments.isEmpty()) {
scope(ScopeType.GENERIC, ", ", false, () -> {
for (Type typeArgument : typeArguments) {
separator();
typeRef(typeArgument);
}
});
}
}
protected abstract void writeDtoTypeRef(ImmutableObjectType type);
public enum ScopeType {
OBJECT("{", "}"),
LIST("[", "]"),
ARGUMENTS("(", ")"),
GENERIC("<", ">"),
BLANK("", "");
final String prefix;
final String suffix;
ScopeType(String prefix, String suffix) {
this.prefix = prefix;
this.suffix = suffix;
}
}
private static class Scope {
private final Scope parent;
final String separator;
final boolean multiLines;
boolean dirty;
Scope(Scope parent, String separator, boolean multiLines) {
this.parent = parent;
this.separator = separator;
this.multiLines = multiLines;
}
void dirty() {
if (!dirty) {
dirty = true;
if (parent != null) {
parent.dirty();
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy