Skip to content

Commit

Permalink
improvements to the jax-rs code generator
Browse files Browse the repository at this point in the history
Signed-off-by: Eric Wittmann <[email protected]>
  • Loading branch information
EricWittmann committed Aug 7, 2019
1 parent c78f488 commit c2d0b53
Show file tree
Hide file tree
Showing 15 changed files with 597 additions and 675 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -191,16 +191,7 @@ protected void generateAll(CodegenInfo info, StringBuilder log, ZipOutputStream
zipOutput.closeEntry();
}

for (CodegenJavaInterface iface : info.getInterfaces()) {
log.append("Generating Interface: " + iface.getPackage() + "." + iface.getName() + "\r\n");
String javaInterface = generateJavaInterface(iface);
String javaInterfaceFileName = javaPackageToZipPath(iface.getPackage()) + iface.getName() + ".java";
log.append("Adding to zip: " + javaInterfaceFileName + "\r\n");
zipOutput.putNextEntry(new ZipEntry(javaInterfaceFileName));
zipOutput.write(javaInterface.getBytes());
zipOutput.closeEntry();
}

// Generate the java beans from data types
IndexedCodeWriter codeWriter = new IndexedCodeWriter();
for (CodegenJavaBean bean : info.getBeans()) {
log.append("Generating Bean: " + bean.getPackage() + "." + bean.getName() + "\r\n");
Expand All @@ -213,6 +204,18 @@ protected void generateAll(CodegenInfo info, StringBuilder log, ZipOutputStream
zipOutput.write(codeWriter.get(key).getBytes());
zipOutput.closeEntry();
}

// Generate the JAX-RS interfaces
for (CodegenJavaInterface iface : info.getInterfaces()) {
log.append("Generating Interface: " + iface.getPackage() + "." + iface.getName() + "\r\n");
String javaInterface = generateJavaInterface(iface);
String javaInterfaceFileName = javaPackageToZipPath(iface.getPackage()) + iface.getName() + ".java";
log.append("Adding to zip: " + javaInterfaceFileName + "\r\n");
zipOutput.putNextEntry(new ZipEntry(javaInterfaceFileName));
zipOutput.write(javaInterface.getBytes());
zipOutput.closeEntry();
}

}

/**
Expand Down Expand Up @@ -244,8 +247,39 @@ protected CodegenInfo getInfoFromApiDoc() throws IOException {
// Then generate the CodegenInfo object.
OpenApi2CodegenVisitor cgVisitor = new OpenApi2CodegenVisitor(this.settings.javaPackage, iVisitor.getInterfaces());
VisitorUtil.visitTree(document, cgVisitor, TraverserDirection.down);

// Now resolve any inline schemas/types
CodegenInfo info = cgVisitor.getCodegenInfo();
info.getInterfaces().forEach( iface -> {
iface.getMethods().forEach( method -> {
method.getArguments().forEach( arg -> {
String argTypeSig = arg.getTypeSignature();
CodegenJavaBean matchingBean = findMatchingBean(info, argTypeSig);
if (matchingBean != null) {
arg.setType(matchingBean.getPackage() + "." + StringUtils.capitalize(matchingBean.getName()));
}
});
});
});

return info;
}

return cgVisitor.getCodegenInfo();
/**
* Find a bean that matches the schema signature.
* @param info
* @param typeSignature
*/
private static CodegenJavaBean findMatchingBean(CodegenInfo info, String typeSignature) {
if (typeSignature == null) {
return null;
}
for (CodegenJavaBean bean : info.getBeans()) {
if (typeSignature.equals(bean.getSignature())) {
return bean;
}
}
return null;
}

/**
Expand Down Expand Up @@ -332,6 +366,9 @@ private String generateJavaInterface(CodegenJavaInterface _interface) {
}
TypeName paramType = generateTypeName(cgArgument.getCollection(), cgArgument.getType(),
cgArgument.getFormat(), cgArgument.getRequired(), defaultParamType);
if (cgArgument.getTypeSignature() != null) {
// TODO try to find a re-usable data type that matches the type signature
}
com.squareup.javapoet.ParameterSpec.Builder paramBuilder = ParameterSpec.builder(paramType,
paramNameToJavaArgName(cgArgument.getName()));
if (cgArgument.getIn().equals("path")) {
Expand All @@ -350,6 +387,10 @@ private String generateJavaInterface(CodegenJavaInterface _interface) {
}
}

// TODO:: error responses (4xx and 5xx)
// Should errors be modeled in some way? JAX-RS has a few ways to handle them. I'm inclined to
// not generate anything in the interface for error responses.

// Javadoc
if (cgMethod.getDescription() != null) {
methodBuilder.addJavadoc(cgMethod.getDescription());
Expand All @@ -374,8 +415,7 @@ private String generateJavaInterface(CodegenJavaInterface _interface) {
* @param required
* @param defaultType
*/
private TypeName generateTypeName(String collection, String type, String format, Boolean required,
TypeName defaultType) {
private TypeName generateTypeName(String collection, String type, String format, Boolean required, TypeName defaultType) {
if (type == null) {
return defaultType;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class CodegenJavaArgument {
private String type;
private String format;
private Boolean required;
private String typeSignature;

/**
* Constructor.
Expand Down Expand Up @@ -118,4 +119,18 @@ public void setRequired(Boolean required) {
this.required = required;
}

/**
* @return the typeSignature
*/
public String getTypeSignature() {
return typeSignature;
}

/**
* @param typeSignature the typeSignature to set
*/
public void setTypeSignature(String typeSignature) {
this.typeSignature = typeSignature;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public class CodegenJavaBean {
private String _package;
private String name;
private JsonNode $schema;
private String signature;

/**
* Constructor.
Expand Down Expand Up @@ -75,4 +76,18 @@ public void setName(String name) {
this.$schema = $schema;
}

/**
* @return the signature
*/
public String getSignature() {
return signature;
}

/**
* @param signature the signature to set
*/
public void setSignature(String signature) {
this.signature = signature;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import io.apicurio.hub.api.codegen.beans.CodegenJavaInterface;
import io.apicurio.hub.api.codegen.beans.CodegenJavaMethod;
import io.apicurio.hub.api.codegen.beans.CodegenJavaReturn;
import io.apicurio.hub.api.codegen.util.SchemaSigner;

/**
* Visitor used to create a Codegen Info object from a OpenAPI document.
Expand All @@ -71,6 +72,11 @@ public class OpenApi2CodegenVisitor extends CombinedVisitorAdapter {

private boolean _processPathItemParams = false;

/**
* Constructor.
* @param packageName
* @param interfaces
*/
public OpenApi2CodegenVisitor(String packageName, List<InterfaceInfo> interfaces) {
this.codegenInfo.setName("Thorntail API");
this.codegenInfo.setVersion("1.0.0");
Expand All @@ -91,7 +97,18 @@ public OpenApi2CodegenVisitor(String packageName, List<InterfaceInfo> interfaces
public CodegenInfo getCodegenInfo() {
return this.codegenInfo;
}


/**
* Creates a unique signature for the given schema. The signature is used to determine whether two schemas
* are the same.
* @param node
*/
private static String createSignature(OasSchema node) {
SchemaSigner signer = new SchemaSigner();
Library.visitNode(node, signer);
return signer.getSignature();
}

/**
* @see io.apicurio.datamodels.combined.visitors.CombinedVisitorAdapter#visitInfo(io.apicurio.datamodels.core.models.common.Info)
*/
Expand Down Expand Up @@ -199,9 +216,12 @@ private void visit20Parameter(Oas20Parameter node) {
if (cgReturn.getCollection() != null) { this._currentArgument.setCollection(cgReturn.getCollection()); }
if (cgReturn.getType() != null) { this._currentArgument.setType(cgReturn.getType()); }
if (cgReturn.getFormat() != null) { this._currentArgument.setFormat(cgReturn.getFormat()); }

this._currentArgument.setTypeSignature(createSignature((OasSchema) node.schema));
} else if (node.type != null) {
if (node.type != null) { this._currentArgument.setType(node.type); }
if (node.format != null) { this._currentArgument.setFormat(node.format); }
// TODO:: sign the argument from the type and format on the node.
}
}
private void visit30Parameter(Oas30Parameter node) {
Expand All @@ -213,13 +233,15 @@ private void visit30Parameter(Oas30Parameter node) {
if (cgReturn.getCollection() != null) { this._currentArgument.setCollection(cgReturn.getCollection()); }
if (cgReturn.getType() != null) { this._currentArgument.setType(cgReturn.getType()); }
if (cgReturn.getFormat() != null) { this._currentArgument.setFormat(cgReturn.getFormat()); }
this._currentArgument.setTypeSignature(createSignature((OasSchema) mediaType.schema));
}
} else if (node.schema != null) {
CodegenJavaReturn cgReturn = this.returnFromSchema((OasSchema) node.schema);
if (cgReturn != null) {
if (cgReturn.getCollection() != null) { this._currentArgument.setCollection(cgReturn.getCollection()); }
if (cgReturn.getType() != null) { this._currentArgument.setType(cgReturn.getType()); }
if (cgReturn.getFormat() != null) { this._currentArgument.setFormat(cgReturn.getFormat()); }
this._currentArgument.setTypeSignature(createSignature((OasSchema) node.schema));
}
}
}
Expand Down Expand Up @@ -295,6 +317,8 @@ public void visitSchemaDefinition(IDefinition node) {
bean.setName(name);
bean.setPackage(this.packageName + ".beans");
bean.set$schema((JsonNode) Library.writeNode((Node) node));
bean.setSignature(createSignature((OasSchema) node));

this.codegenInfo.getBeans().add(bean);
}

Expand Down
Loading

0 comments on commit c2d0b53

Please sign in to comment.