Skip to content

Commit

Permalink
293 asyncapi $ref resolution are always a class (#300)
Browse files Browse the repository at this point in the history
  • Loading branch information
jemacineiras committed Nov 21, 2023
1 parent 724e307 commit c549887
Show file tree
Hide file tree
Showing 30 changed files with 616 additions and 105 deletions.
26 changes: 13 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Maven and Gradle
- [Getting Started](#getting-started)
- [Initial Considerations](#initial-considerations)
- [Usage](#usage)
- [Property Validation](#properties-validation)
- [Property Validation](#property-validation)

## Main Configuration

Expand Down Expand Up @@ -60,7 +60,7 @@ As commented above, they both could be used at the same time, setting a double
<plugin>
<groupId>com.sngular</groupId>
<artifactId>scs-multiapi-maven-plugin</artifactId>
<version>5.0.2</version>
<version>5.1.0</version>
<executions>
<execution>
<id>asyncapi</id>
Expand Down Expand Up @@ -94,7 +94,7 @@ As commented above, they both could be used at the same time, setting a double
```

In the example above, you can see a partial configuration for the plugin with
a double *execution*. This makes neccesary to set an `id` for each execution,
a double *execution*. This makes necessary to set an `id` for each execution,
`asyncapi` and `openapi` in this case.

In the case that you only want to run one of the goals of the plugin, you only
Expand All @@ -113,8 +113,8 @@ Apply the plugin in the `build.gradle` file and invoke the task.

```groovy
plugins {
id 'java'
id 'com.sngular.scs-multiapi-gradle-plugin' version '5.0.2'
id "java"
id "com.sngular.scs-multiapi-gradle-plugin' version '5.1.0"
openapimodel {
Expand Down Expand Up @@ -153,7 +153,7 @@ which the plugin is designed.
<plugin>
<groupId>com.sngular</groupId>
<artifactId>scs-multiapi-maven-plugin</artifactId>
<version>5.0.2</version>
<version>5.1.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
Expand Down Expand Up @@ -466,7 +466,7 @@ public interface Mapper {
```java

@Component
public class subscribeOperation implements ISubscribeOperation {
public class SubscribeOperation implements ISubscribeOperation {

private final Mapper mapper;

Expand Down Expand Up @@ -576,7 +576,7 @@ file. Here is an example of a basic configuration:
<plugin>
<groupId>com.sngular</groupId>
<artifactId>scs-multiapi-maven-plugin</artifactId>
<version>5.0.2</version>
<version>5.1.0</version>
<executions>
<execution>
<goals>
Expand Down Expand Up @@ -692,12 +692,12 @@ RestClient and the WebClient will be located, if this option is set in any
of the specFiles, and the name of the folder where the generated sources will
be saved in the api of the project.

| Name | Description | Example |
|-----------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------|
| Name | Description | Example |
|-----------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------|
| clientPackage | Path where the RestClient and/or WebClient are located | com.sngular.apigenerator.openapi.client |
| [generatedSourcesFolder](#generated-sources-folder) | Name of the folder, inside `target`, where the files will be located. By defaut it's `generated-sources` | generated-sources |
| overwriteModel | Boolean value to decide if you want your models to be overwritten if two or more models have the same name. True means that models will be overwritten and if false is set, it will throw an exception if two models share the same name. It is initialized to false by default | false |
| springBootVersion | The version of spring to target during generation. It's default value is `2`. | 3
| [generatedSourcesFolder](#generated-sources-folder) | Name of the folder, inside `target`, where the files will be located. By defaut it's `generated-sources` | generated-sources |
| overwriteModel | Boolean value to decide if you want your models to be overwritten if two or more models have the same name. True means that models will be overwritten and if false is set, it will throw an exception if two models share the same name. It is initialized to false by default | false |
| springBootVersion | The version of spring to target during generation. It's default value is `2`. | 3 |

We must clarify that the options to make calls are configured under the
RestClient or WebClient specifications as indicated above in the configuration
Expand Down
8 changes: 8 additions & 0 deletions checkstyle.xml
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,14 @@
<property name="files" value="[/\\].*AsyncApiGenerator.java"/>
<property name="checks" value="ParameterNumber"/>
</module>
<module name="SuppressionSingleFilter">
<property name="files" value="[/\\].*OpenApiGenerator.java"/>
<property name="checks" value="ParameterNumber"/>
</module>
<module name="SuppressionSingleFilter">
<property name="files" value="[/\\].*MapperContentUtil.java"/>
<property name="checks" value="ParameterNumber"/>
</module>
<module name="SuppressionSingleFilter">
<property name="files" value="[\\/]test[\\/].*"/>
<property name="checks" value="[a-zA-Z0-9]*"/>
Expand Down
2 changes: 1 addition & 1 deletion multiapi-engine/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>com.sngular</groupId>
<artifactId>multiapi-engine</artifactId>
<version>5.0.2</version>
<version>5.1.0</version>
<packaging>jar</packaging>

<properties>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ public AsyncApiGenerator(final Integer springBootVersion, final File targetFolde
this.processedGeneratedSourcesFolder = processedGeneratedSourcesFolder;
this.targetFolder = targetFolder;
this.baseDir = baseDir;
templateFactory = new TemplateFactory();
targetFileFilter = (dir, name) -> name.toLowerCase().contains(targetFolder.toPath().getFileName().toString());
this.templateFactory = new TemplateFactory();
this.targetFileFilter = (dir, name) -> name.toLowerCase().contains(targetFolder.toPath().getFileName().toString());
this.springBootVersion = springBootVersion;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package com.sngular.api.generator.plugin.asyncapi.model;

import java.util.Objects;

import com.sngular.api.generator.plugin.asyncapi.util.BindingTypeEnum;
import lombok.Builder;
import lombok.Value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import com.sngular.api.generator.plugin.asyncapi.exception.FileSystemException;
import com.sngular.api.generator.plugin.asyncapi.exception.NonSupportedBindingException;
import com.sngular.api.generator.plugin.asyncapi.model.MethodObject;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,13 @@ private static List<SchemaFieldObject> getFields(
if (OBJECT.equalsIgnoreCase(model.get(TYPE).textValue())) {
fieldObjectArrayList.addAll(processFieldObject(totalSchemas, model, prefix, suffix, modelToBuildList, parentPackage));
} else if (ARRAY.equalsIgnoreCase(model.get(TYPE).textValue())) {
fieldObjectArrayList.add(processFieldObjectList(totalSchemas, "", model, required, prefix, suffix, modelToBuildList, parentPackage));
fieldObjectArrayList.add(processFieldObjectList(totalSchemas, "", model, required, prefix, suffix, modelToBuildList, parentPackage, null));
} else if ("enum".equalsIgnoreCase(model.get(TYPE).textValue())) {
fieldObjectArrayList.add(processFieldObjectList(totalSchemas, "", model, required, prefix, suffix, modelToBuildList, parentPackage));
fieldObjectArrayList.add(processFieldObjectList(totalSchemas, "", model, required, prefix, suffix, modelToBuildList, parentPackage, null));
}
} else if (ApiTool.hasRef(model)) {
fieldObjectArrayList.addAll(processFieldObject(totalSchemas, totalSchemas.get(MapperUtil.buildKey(MapperUtil.splitName(ApiTool.getRefValue(model)))), prefix, suffix,
final var splitName = MapperUtil.splitName(ApiTool.getRefValue(model));
fieldObjectArrayList.addAll(processFieldObject(totalSchemas, totalSchemas.get(MapperUtil.buildKey(splitName)), prefix, suffix,
modelToBuildList, parentPackage));
} else if (model.elements().hasNext()) {
fieldObjectArrayList.addAll(processFieldObject(totalSchemas, model, prefix, suffix, modelToBuildList, parentPackage));
Expand All @@ -180,8 +181,8 @@ private static List<SchemaFieldObject> processFieldObject(
while (propertiesIt.hasNext()) {
final var property = propertiesIt.next();
fieldObjectArrayList.add(processFieldObjectList(totalSchemas, property, model.get(PROPERTIES).path(property), requiredSet.contains(property), prefix, suffix,
modelToBuildList, parentPackage));
if (model.get(PROPERTIES).path(property).has(REF)) {
modelToBuildList, parentPackage, null));
if (model.get(PROPERTIES).path(property).has(REF) && !totalSchemas.containsKey(createKey(parentPackage, property.toUpperCase(), "/"))) {
modelToBuildList.add(MapperUtil.getLongRefClass(model.get(PROPERTIES).path(property)));
}
}
Expand Down Expand Up @@ -215,18 +216,17 @@ private static SchemaFieldObject solveElement(
if (element.has(REF)) {
final String schemaName = MapperUtil.getLongRefClass(element);
final var schemaToProcess = totalSchemas.get(schemaName.toUpperCase());
result = processFieldObjectList(totalSchemas, schemaName, schemaToProcess, required, prefix, suffix, modelToBuildList, null);
result = processFieldObjectList(totalSchemas, schemaName, schemaToProcess, required, prefix, suffix, modelToBuildList, null, null);
result.setRequired(false);
} else {
result = processFieldObjectList(totalSchemas, "", element, required, prefix, suffix, modelToBuildList, null);
result = processFieldObjectList(totalSchemas, "", element, required, prefix, suffix, modelToBuildList, null, null);
}
return result;
}

@SuppressWarnings("checkstyle:ParameterNumber")
private static SchemaFieldObject processFieldObjectList(
final Map<String, JsonNode> totalSchemas, final String propertyName, final JsonNode schema, final boolean required,
final String prefix, final String suffix, final Collection<String> modelToBuildList, final String modelPackage) {
final String prefix, final String suffix, final Collection<String> modelToBuildList, final String modelPackage, final String className) {
final SchemaFieldObject fieldObject;
final var name = schema.has("name") ? schema.get("name").textValue() : propertyName;
if (ApiTool.hasType(schema)) {
Expand All @@ -239,10 +239,11 @@ private static SchemaFieldObject processFieldObjectList(
.restrictions(new SchemaFieldObjectProperties())
.dataType(MapperUtil.getSimpleType(schema, prefix, suffix))
.build();
setFieldType(fieldObject, schema, required, prefix, suffix);
if (StringUtils.isNotEmpty(propertyName) && !totalSchemas.containsKey(propertyName)) {
totalSchemas.put(createKey(modelPackage, propertyName.toUpperCase(), "/"), schema);
modelToBuildList.add(createKey(modelPackage.toLowerCase(), propertyName, "."));
setFieldType(fieldObject, schema, required, prefix, suffix, className);
final var schemaName = StringUtils.defaultString(className, propertyName);
if (StringUtils.isNotEmpty(schemaName) && !totalSchemas.containsKey(createKey(modelPackage, schemaName.toUpperCase(), "/"))) {
totalSchemas.put(createKey(modelPackage, schemaName.toUpperCase(), "/"), schema);
modelToBuildList.add(createKey(modelPackage.toLowerCase(), schemaName, "."));
}
} else if (ApiTool.hasItems(schema)) {
final var items = ApiTool.getItems(schema);
Expand Down Expand Up @@ -275,14 +276,9 @@ private static SchemaFieldObject processFieldObjectList(
fieldObject.setRequired(required);
}
} else if (ApiTool.hasRef(schema)) {
fieldObject =
SchemaFieldObject
.builder()
.baseName(name)
.dataTypeSimple(MapperUtil.getSimpleType(schema, prefix, suffix))
.restrictions(new SchemaFieldObjectProperties())
.build();
setFieldType(fieldObject, schema, required, prefix, suffix);
final var splitName = MapperUtil.splitName(ApiTool.getRefValue(schema));
final var solvedRef = totalSchemas.get(getComponent(splitName));
fieldObject = processFieldObjectList(totalSchemas, name, solvedRef, required, prefix, suffix, modelToBuildList, modelPackage, splitName[splitName.length - 1]);
} else {
fieldObject = SchemaFieldObject
.builder()
Expand Down Expand Up @@ -373,7 +369,7 @@ private static void setFieldProperties(final SchemaFieldObject fieldObject, fina
}
}

private static void setFieldType(final SchemaFieldObject field, final JsonNode value, final boolean required, final String prefix, final String suffix) {
private static void setFieldType(final SchemaFieldObject field, final JsonNode value, final boolean required, final String prefix, final String suffix, final String className) {
field.setRequired(required);
if (ApiTool.hasType(value)) {
if (ARRAY.equalsIgnoreCase(ApiTool.getType(value))) {
Expand All @@ -391,7 +387,11 @@ private static void setFieldType(final SchemaFieldObject field, final JsonNode v
if (ApiTool.hasRef(value)) {
typeObject = MapperUtil.getRef(value, prefix, suffix);
} else {
typeObject = MapperUtil.getPojoName(field.getBaseName(), prefix, suffix);
if (StringUtils.isEmpty(className)) {
typeObject = MapperUtil.getPojoName(field.getBaseName(), prefix, suffix);
} else {
typeObject = MapperUtil.getPojoName(className, prefix, suffix);
}
}
field.setImportClass(getImportClass(typeObject));
field.setDataType(typeObject);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;

import com.sngular.api.generator.plugin.asyncapi.exception.FileSystemException;

public class DirectoryFileLocation implements FileLocation {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.sngular.api.generator.plugin.common.tools;

import java.nio.file.Path;
import java.util.Map;

import com.fasterxml.jackson.databind.JsonNode;
import com.sngular.api.generator.plugin.openapi.utils.MapperUtil;
import com.sngular.api.generator.plugin.openapi.utils.OpenApiUtil;
import org.apache.commons.lang3.StringUtils;

public class SchemaUtil {

protected SchemaUtil() {
}

public static JsonNode solveRef(final String refValue, final Map<String, JsonNode> schemaMap, final Path rootFilePath) {
JsonNode solvedRef;
if (StringUtils.isNotEmpty(refValue)) {
if (refValue.startsWith("#")) {
final String refSchemaName = MapperUtil.getRefSchemaName(refValue);
solvedRef = schemaMap.get(refSchemaName);
} else {
final var refValueArr = refValue.split("#");
final var filePath = refValueArr[0];
solvedRef = OpenApiUtil.getPojoFromRef(rootFilePath.toAbsolutePath(), filePath);
final var refName = MapperUtil.getRefSchemaName(refValueArr[1]);
schemaMap.putAll(ApiTool.getComponentSchemas(solvedRef));
solvedRef = solvedRef.findValue(refName);
}
} else {
solvedRef = null;
}
return solvedRef;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.util.Objects;
import java.util.Set;
import java.util.regex.Pattern;

import com.fasterxml.jackson.databind.JsonNode;
import com.sngular.api.generator.plugin.PluginConstants;
import com.sngular.api.generator.plugin.common.tools.ApiTool;
Expand Down Expand Up @@ -254,19 +255,24 @@ private void processModels(
final SpecFile specFile, final String fileModelToSave, final String modelPackage, final Map<String, JsonNode> basicSchemaMap,
final boolean overwrite) {
final Map<String, SchemaObject> builtSchemasMap = new HashMap<>();
basicSchemaMap.forEach((schemaName, basicSchema) -> {
if (!overwrite && !overwriteModelList.add(schemaName + modelPackage)) {
throw new DuplicateModelClassException(schemaName, modelPackage);
}
basicSchemaMap.forEach((schemaName, basicSchema) ->
processModel(specFile, fileModelToSave, modelPackage, basicSchemaMap, overwrite, schemaName, basicSchema, builtSchemasMap)
);
}

if (ApiTool.hasRef(basicSchema)) {
final var refSchema = MapperUtil.getRefSchemaName(basicSchema);
builtSchemasMap.putAll(writeModel(specFile, fileModelToSave, refSchema, basicSchemaMap.get(refSchema), basicSchemaMap, builtSchemasMap));
} else if (!ApiTool.isArray(basicSchema) && !TypeConstants.STRING.equalsIgnoreCase(ApiTool.getType(basicSchema))) {
builtSchemasMap.putAll(writeModel(specFile, fileModelToSave, schemaName, basicSchema, basicSchemaMap, builtSchemasMap));
}
});
private void processModel(
final SpecFile specFile, final String fileModelToSave, final String modelPackage, final Map<String, JsonNode> basicSchemaMap, final boolean overwrite,
final String schemaName, final JsonNode basicSchema, final Map<String, SchemaObject> builtSchemasMap) {
if (!overwrite && !overwriteModelList.add(schemaName + modelPackage)) {
throw new DuplicateModelClassException(schemaName, modelPackage);
}

if (ApiTool.hasRef(basicSchema)) {
final var refSchema = MapperUtil.getRefSchemaName(basicSchema);
builtSchemasMap.putAll(writeModel(specFile, fileModelToSave, refSchema, basicSchemaMap.get(refSchema), basicSchemaMap, builtSchemasMap));
} else if (!ApiTool.isArray(basicSchema) && !TypeConstants.STRING.equalsIgnoreCase(ApiTool.getType(basicSchema))) {
builtSchemasMap.putAll(writeModel(specFile, fileModelToSave, schemaName, basicSchema, basicSchemaMap, builtSchemasMap));
}
}

private Map<String, SchemaObject> writeModel(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;

import com.fasterxml.jackson.databind.JsonNode;
import lombok.AllArgsConstructor;
import lombok.Builder;
Expand Down
Loading

0 comments on commit c549887

Please sign in to comment.