diff --git a/multiapi-engine/pom.xml b/multiapi-engine/pom.xml
index ca51f409..d9368599 100644
--- a/multiapi-engine/pom.xml
+++ b/multiapi-engine/pom.xml
@@ -4,7 +4,7 @@
com.sngular
multiapi-engine
- 6.7.3
+ 6.7.4
jar
diff --git a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/common/tools/ApiTool.java b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/common/tools/ApiTool.java
index 4397ce00..d9309609 100644
--- a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/common/tools/ApiTool.java
+++ b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/common/tools/ApiTool.java
@@ -417,6 +417,26 @@ public static JsonNode getPatternProperties(final JsonNode schema) {
return getNode(schema, "patternProperties");
}
+ public static boolean isInlineObject(final JsonNode schema) {
+ return Objects.nonNull(schema) && schema.isObject() && !hasType(schema) && !hasNode(schema, "properties")
+ && !hasNode(schema, "$ref") && !isComposed(schema) && !hasNode(schema, "items") && !hasNode(schema, "enum")
+ && !hasNode(schema, "additionalProperties") && !hasNode(schema, "patternProperties")
+ && hasNonSchemaFields(schema);
+ }
+
+ private static boolean hasNonSchemaFields(final JsonNode schema) {
+ final Iterator> fields = schema.fields();
+ return fields.hasNext() && !isSchemaKeyword(fields.next().getKey());
+ }
+
+ private static boolean isSchemaKeyword(final String fieldName) {
+ return "type".equals(fieldName) || "title".equals(fieldName) || "description".equals(fieldName)
+ || "required".equals(fieldName) || "nullable".equals(fieldName) || "deprecated".equals(fieldName)
+ || "example".equals(fieldName) || "default".equals(fieldName) || "format".equals(fieldName)
+ || "const".equals(fieldName) || "readOnly".equals(fieldName) || "writeOnly".equals(fieldName)
+ || "discriminator".equals(fieldName) || "xml".equals(fieldName) || "externalDocs".equals(fieldName);
+ }
+
public static boolean hasPrefixItems(final JsonNode schema) {
return hasNode(schema, "prefixItems");
}
diff --git a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/common/tools/ModelBuilder.java b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/common/tools/ModelBuilder.java
index 1951328a..67b509d6 100644
--- a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/common/tools/ModelBuilder.java
+++ b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/common/tools/ModelBuilder.java
@@ -187,6 +187,8 @@ private static Set getFields(
final var refSchema = totalSchemas.get(MapperUtil.getRefSchemaKey(schema));
ApiTool.getProperties(refSchema).forEachRemaining(processProperties(buildingSchema, totalSchemas, compositedSchemas, fieldObjectArrayList, specFile, refSchema, antiLoopList,
baseDir));
+ } else if (ApiTool.isInlineObject(schema)) {
+ schema.fields().forEachRemaining(processProperties(nameSchema, totalSchemas, compositedSchemas, fieldObjectArrayList, specFile, schema, antiLoopList, baseDir));
} else {
fieldObjectArrayList.add(SchemaFieldObject.builder()
.baseName(ApiTool.getName(schema))
diff --git a/multiapi-engine/src/test/java/com/sngular/api/generator/plugin/asyncapi/v2/AsyncApiGeneratorFixtures.java b/multiapi-engine/src/test/java/com/sngular/api/generator/plugin/asyncapi/v2/AsyncApiGeneratorFixtures.java
index 38243d97..6b52d9d0 100644
--- a/multiapi-engine/src/test/java/com/sngular/api/generator/plugin/asyncapi/v2/AsyncApiGeneratorFixtures.java
+++ b/multiapi-engine/src/test/java/com/sngular/api/generator/plugin/asyncapi/v2/AsyncApiGeneratorFixtures.java
@@ -9,11 +9,14 @@
import static java.util.Collections.singletonList;
import java.io.File;
+import java.io.IOException;
import java.net.URISyntaxException;
+import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
+import java.util.stream.Stream;
import com.sngular.api.generator.plugin.asyncapi.parameter.OperationParameterObject;
import com.sngular.api.generator.plugin.asyncapi.parameter.SpecFile;
@@ -145,6 +148,25 @@ public class AsyncApiGeneratorFixtures {
.build()
);
+ static final List TEST_ISSUE_248_GENERATION = List.of(
+ SpecFile
+ .builder()
+ .filePath("asyncapigenerator/v2/testIssueCustomValidators248/event-api.yml")
+ .consumer(OperationParameterObject.builder()
+ .ids("publishOrder")
+ .modelNameSuffix("DTO")
+ .apiPackage("com.sngular.scsplugin.issue248.model.event.consumer")
+ .modelPackage("com.sngular.scsplugin.issue248.model.event")
+ .build())
+ .supplier(OperationParameterObject.builder()
+ .ids("subscribeOrder")
+ .modelNameSuffix("DTO")
+ .apiPackage("com.sngular.scsplugin.issue248.model.event.producer")
+ .modelPackage("com.sngular.scsplugin.issue248.model.event")
+ .build())
+ .build()
+ );
+
static final List TEST_CUSTOM_VALIDATORS_DIFFERENT_PACKAGES = List.of(
SpecFile
.builder()
@@ -754,6 +776,34 @@ static Function validateCustomValidators(final int springBootVers
customValidatorTest(path, expectedValidatorFiles, DEFAULT_CUSTOM_VALIDATOR_FOLDER);
}
+ static Function validateIssue248PackageFolderAlignment() {
+ return path -> {
+ final Path pathToTarget = Path.of(path.toString(), "target", "generated");
+ Boolean result = Boolean.TRUE;
+ try (final Stream javaFiles = Files.walk(pathToTarget)) {
+ final List generatedFiles = javaFiles
+ .filter(Files::isRegularFile)
+ .filter(p -> p.toString().endsWith(".java"))
+ .toList();
+ Assertions.assertThat(generatedFiles).isNotEmpty();
+ for (final Path javaFile : generatedFiles) {
+ final String packageDeclaration = Files.readAllLines(javaFile).stream()
+ .filter(line -> line.startsWith("package "))
+ .findFirst()
+ .map(line -> line.replace("package ", "").replace(";", "").trim())
+ .orElseThrow();
+ final String expectedPackage = pathToTarget.relativize(javaFile).getParent().toString().replace(File.separatorChar, '.');
+ Assertions.assertThat(packageDeclaration)
+ .overridingErrorMessage("File %s declares package %s but lives in folder matching %s", javaFile, packageDeclaration, expectedPackage)
+ .isEqualTo(expectedPackage);
+ }
+ } catch (final IOException e) {
+ result = Boolean.FALSE;
+ }
+ return result;
+ };
+ }
+
static Function validateCustomValidatorsDifferentPackages() {
final String DEFAULT_CONSUMER_MODEL_FOLDER = "generated/com/sngular/scsplugin/customvalidatordiff/model/event/consumer";
diff --git a/multiapi-engine/src/test/java/com/sngular/api/generator/plugin/asyncapi/v2/AsyncApiGeneratorTest.java b/multiapi-engine/src/test/java/com/sngular/api/generator/plugin/asyncapi/v2/AsyncApiGeneratorTest.java
index 634db9aa..88df2c9e 100644
--- a/multiapi-engine/src/test/java/com/sngular/api/generator/plugin/asyncapi/v2/AsyncApiGeneratorTest.java
+++ b/multiapi-engine/src/test/java/com/sngular/api/generator/plugin/asyncapi/v2/AsyncApiGeneratorTest.java
@@ -70,6 +70,8 @@ static Stream fileSpecToProcess() {
Arguments.of("TestCustomValidators", AsyncApiGeneratorFixtures.TEST_CUSTOM_VALIDATORS, AsyncApiGeneratorFixtures.validateCustomValidators(SPRING_BOOT_VERSION)),
Arguments.of("TestCustomValidatorsDifferentPackages", AsyncApiGeneratorFixtures.TEST_CUSTOM_VALIDATORS_DIFFERENT_PACKAGES,
AsyncApiGeneratorFixtures.validateCustomValidatorsDifferentPackages()),
+ Arguments.of("TestIssue248CustomValidators", AsyncApiGeneratorFixtures.TEST_ISSUE_248_GENERATION,
+ AsyncApiGeneratorFixtures.validateIssue248PackageFolderAlignment()),
Arguments.of("TestModelClassExceptionGeneration", AsyncApiGeneratorFixtures.TEST_MODEL_CLASS_EXCEPTION_GENERATION,
AsyncApiGeneratorFixtures.validateTestModelClassExceptionGeneration()),
Arguments.of("TestNoSchemas", AsyncApiGeneratorFixtures.TEST_NO_SCHEMAS, AsyncApiGeneratorFixtures.validateNoSchemas()),
diff --git a/multiapi-engine/src/test/resources/asyncapigenerator/v2/testIssueCustomValidators248/event-api.yml b/multiapi-engine/src/test/resources/asyncapigenerator/v2/testIssueCustomValidators248/event-api.yml
new file mode 100644
index 00000000..70f75b1a
--- /dev/null
+++ b/multiapi-engine/src/test/resources/asyncapigenerator/v2/testIssueCustomValidators248/event-api.yml
@@ -0,0 +1,98 @@
+asyncapi: 2.3.0
+info:
+ title: Order Service
+ version: 1.0.0
+ description: Order management Service
+servers:
+ development:
+ url: development.gigantic-server.com
+ description: Development server
+ protocol: kafka
+ protocolVersion: 0.9.1
+ staging:
+ url: staging.gigantic-server.com
+ description: Staging server
+ protocol: kafka
+ protocolVersion: 0.9.1
+ production:
+ url: api.gigantic-server.com
+ description: Production server
+ protocol: kafka
+ protocolVersion: 0.9.1
+channels:
+ order/created:
+ publish:
+ operationId: "publishOrder"
+ message:
+ $ref: '#/components/messages/OrderCreatedEvent'
+ order/createCommand:
+ subscribe:
+ operationId: "subscribeOrder"
+ message:
+ $ref: '#/components/messages/CreateOrderEvent'
+components:
+ messages:
+ OrderCreatedEvent:
+ payload:
+ $ref: '#/components/schemas/Order'
+ CreateOrderEvent:
+ payload:
+ order:
+ $ref: '#/components/schemas/Order'
+ waiter:
+ $ref: '#/components/schemas/Waiter'
+ schemas:
+ Waiter:
+ type: object
+ properties:
+ ref:
+ type: string
+ timestamp:
+ type: string
+ format: 'dd/mm/yyyy hh:MM:sss'
+ table:
+ type: string
+ Order:
+ type: object
+ properties:
+ ref:
+ type: string
+ clientRef:
+ type: string
+ amount:
+ type: string
+ format: decimal
+ lines:
+ type: array
+ items:
+ $ref: '#/components/schemas/OrderLine'
+ OrderLine:
+ type: object
+ required:
+ - ref
+ - products
+ properties:
+ ref:
+ type: string
+ products:
+ type: array
+ items:
+ $ref: '#/components/schemas/OrderProduct'
+ OrderProduct:
+ type: object
+ required:
+ - ref
+ - productRef
+ - price
+ - quantity
+ properties:
+ ref:
+ type: string
+ productRef:
+ type: string
+ price:
+ type: string
+ format: decimal
+ quantity:
+ type: string
+ format: decimal
diff --git a/scs-multiapi-gradle-plugin/build.gradle b/scs-multiapi-gradle-plugin/build.gradle
index 26780f99..64415ba8 100644
--- a/scs-multiapi-gradle-plugin/build.gradle
+++ b/scs-multiapi-gradle-plugin/build.gradle
@@ -21,7 +21,7 @@ repositories {
}
group = 'com.sngular'
-version = '6.7.3'
+version = '6.7.4'
def SCSMultiApiPluginGroupId = group
def SCSMultiApiPluginVersion = version
@@ -31,7 +31,7 @@ dependencies {
shadow localGroovy()
shadow gradleApi()
- implementation 'com.sngular:multiapi-engine:6.7.3'
+ implementation 'com.sngular:multiapi-engine:6.7.4'
testImplementation 'org.assertj:assertj-core:3.24.2'
testImplementation 'com.puppycrawl.tools:checkstyle:10.12.3'
testImplementation 'org.junit.platform:junit-platform-launcher:1.9.2'
@@ -100,7 +100,7 @@ testing {
integrationTest(JvmTestSuite) {
dependencies {
- implementation 'com.sngular:scs-multiapi-gradle-plugin:6.7.3'
+ implementation 'com.sngular:scs-multiapi-gradle-plugin:6.7.4'
implementation 'org.assertj:assertj-core:3.24.2'
}
diff --git a/scs-multiapi-maven-plugin/pom.xml b/scs-multiapi-maven-plugin/pom.xml
index 39a9ef94..a2a7ac93 100644
--- a/scs-multiapi-maven-plugin/pom.xml
+++ b/scs-multiapi-maven-plugin/pom.xml
@@ -4,7 +4,7 @@
com.sngular
scs-multiapi-maven-plugin
- 6.7.3
+ 6.7.4
maven-plugin
AsyncApi - OpenApi Code Generator Maven Plugin
@@ -271,7 +271,7 @@
com.sngular
multiapi-engine
- 6.7.3
+ 6.7.4
org.apache.maven