diff --git a/Example-Test-Plan.jmx b/Example-Test-Plan.jmx
index e157244a..a014aa80 100644
--- a/Example-Test-Plan.jmx
+++ b/Example-Test-Plan.jmx
@@ -16,10 +16,10 @@
continue
false
- 1
+ 1000
- 1
- 1
+ 1000
+ 10
false
@@ -376,7 +376,7 @@
false
- customer_account.billing_party.party_contact[].contact_id
+ customer_account.billing_party.party_contact[4].contact_id
0
int
@@ -387,7 +387,7 @@
customer_account.billing_party.party_contact[].contact_name
0
string
-
+ Juan, Pedro, tomas, brais, jose, Adrian
true
false
@@ -408,7 +408,7 @@
false
- details.in_details.customs_details.party.party_contact[].contact_id
+ details.in_details.customs_details.party.party_contact[6].contact_id
0
int
@@ -424,10 +424,10 @@
false
- details.in_details.customs_details.party.p_contact[].contact_id
+ details.in_details.customs_details.party.p_contact[2].contact_id
0
- int
-
+ seq
+ 2000
true
false
diff --git a/docs/_Sidebar.md b/docs/_Sidebar.md
index ba20f1d8..78fd07a7 100644
--- a/docs/_Sidebar.md
+++ b/docs/_Sidebar.md
@@ -16,6 +16,7 @@
- [Consumer configuration](consumer-configuration.md)
- [Schemas](schemas.md)
- [Schema Registry](schema-registry.md)
+ - [Asyncapi support](asyncapi.md)
# Knowledge center
- [How to run a test plan](how-to-run.md)
diff --git a/docs/asyncapi.md b/docs/asyncapi.md
new file mode 100644
index 00000000..997f493a
--- /dev/null
+++ b/docs/asyncapi.md
@@ -0,0 +1,22 @@
+# Asyncapi Support
+
+Here you can find the way to use your asyncapi.yml definition (v. 2.X.X) to produce a performance load test.
+The only requirement is to use the AsyncApi Sampler component. There you can load the asyncapi file into the plugin.
+
+
+
+Once the file is loaded, information will appear in the elements below.
+First tab you can see the broker configuration where you can choose to which broker you want to connect to.
+
+
+
+Once the broker has been choose the data will be loaded. By default the first server configuration will be selected
+
+
+
+In order to choose which payload you want to use for the test just move to the second tab and use the combo to select which topic you want to use.
+As for in AsyncApi specification channel/topic contains the payload will be transmitted.
+
+
+
+Data generation use the same engine that the rest of the samplers so information from [schemas page](schemas.md) apply.
\ No newline at end of file
diff --git a/docs/getting-started.md b/docs/getting-started.md
index 02f5bdaf..84675b6e 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -6,10 +6,8 @@ Now that you know what KLoadGen is and that you are familiar with its components
You will need these tools to start using the plugin:
-- JDK/JRE 11+
- - (17 recommended)
-- JMeter 5.4+
- - (5.6.2 recommended)
+- JDK/JRE 17+
+- JMeter 5.6.2+
- Maven
## Quickstart
diff --git a/docs/images/AsyncApiComponent-ComboBroker.png b/docs/images/AsyncApiComponent-ComboBroker.png
new file mode 100644
index 00000000..cd363ab5
Binary files /dev/null and b/docs/images/AsyncApiComponent-ComboBroker.png differ
diff --git a/docs/images/AsyncApiComponent-FileLoaded.png b/docs/images/AsyncApiComponent-FileLoaded.png
new file mode 100644
index 00000000..05d29707
Binary files /dev/null and b/docs/images/AsyncApiComponent-FileLoaded.png differ
diff --git a/docs/images/AsyncApiComponent-SchemaLoaded.png b/docs/images/AsyncApiComponent-SchemaLoaded.png
new file mode 100644
index 00000000..883b4222
Binary files /dev/null and b/docs/images/AsyncApiComponent-SchemaLoaded.png differ
diff --git a/docs/images/AsyncapiComponent.png b/docs/images/AsyncapiComponent.png
new file mode 100644
index 00000000..ae5f31e0
Binary files /dev/null and b/docs/images/AsyncapiComponent.png differ
diff --git a/pom-maven-central.xml b/pom-maven-central.xml
index 71ca6d5c..4a9c9cee 100644
--- a/pom-maven-central.xml
+++ b/pom-maven-central.xml
@@ -7,7 +7,7 @@
kloadgen
- 5.6.10
+ 5.7.0
KLoadGen
Load Generation Jmeter plugin for Kafka Cluster. Supporting AVRO, JSON Schema and Protobuf schema types. Generate Artificial
@@ -225,24 +225,24 @@
Europe/Madrid
- nuriaricorf
- Nuria Rico Freire
- nuria.rico@sngular.com
+ rabad-sng
+ Raúl Abad
+ raul.abad@sngular.com
Sngular
- https://sngular.github.io/
+ https://www.sngular.com
- Junior Developer
+ Senior Backend Developer
Europe/Madrid
- rabad-sng
- Raúl Abad
- raul.abad@sngular.com
+ nuriaricorf
+ Nuria Rico Freire
+ nuria.rico@sngular.com
Sngular
- https://www.sngular.com
+ https://sngular.github.io/
- Senior Backend Developer
+ Junior Developer
Europe/Madrid
@@ -306,6 +306,27 @@
Roberto Riveira Veiga
roberto.riveira@sngular.com
Sngular
+ https://www.sngular.com
+
+ Trainee Backend Developer
+
+
+
+ GraciMndzSNG
+ Graciela Méndez Olmos
+ graciela.mendez@sngular.com
+ Sngular
+ https://sngular.github.io/
+
+ Backend Developer
+
+ Europe/Madrid
+
+
+ pablorodriguez-sngular
+ Pablo Rodríguez Pérez
+ pablo.rodriguezp@sngular.com
+ Sngular
https://sngular.github.io/
Backend Developer
@@ -335,7 +356,7 @@
3.24.2
1.2.0
1.5.1
- 1.11.2
+ 1.11.3
1.9.4
4.4
3.12.0
@@ -358,6 +379,8 @@
2.0.0-alpha1
1.3.1
2.35.1
+ 2.15.2
+ 2.15.3
@@ -395,12 +418,12 @@
com.fasterxml.jackson.core
jackson-core
- 2.15.2
+ ${jackson-annotations.version}
com.fasterxml.jackson.core
jackson-annotations
- 2.15.2
+ ${jackson-annotations.version}
org.projectlombok
@@ -408,6 +431,11 @@
${lombok.version}
provided
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-yaml
+ ${jackson-dataformat-yaml.version}
+
org.apache.commons
commons-lang3
@@ -686,6 +714,7 @@
maven-checkstyle-plugin
checkstyle.xml
+ UTF-8
true
true
false
diff --git a/pom.xml b/pom.xml
index 1bd1946a..508361d3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,7 +7,7 @@
kloadgen
- 5.6.12
+ 5.8.0
KLoadGen
Load Generation Jmeter plugin for Kafka Cluster. Supporting AVRO, JSON Schema and Protobuf schema types. Generate Artificial
@@ -20,7 +20,7 @@
Mozilla Public License 2.0
https://github.com/sngular/kloadgen/blob/master/LICENSE
repo
-
+
@@ -370,15 +370,17 @@
5.8.2
7.1.1
2.4.3.Final
- 3.5.1
+ 3.6.1
1.18.22
0.9.5
4.2.0
UTF-8
4.5.0
- 2.0.0-alpha1
+ 2.0.9
1.3.1
- 2.35.1
+ 3.0.0-beta-4
+ 2.15.2
+ 2.15.3
@@ -411,17 +413,26 @@
com.fasterxml.jackson.core
jackson-core
+
+ org.apache.commons
+ commons-compress
+
+
+ org.apache.commons
+ commons-compress
+ 1.24.0
+
com.fasterxml.jackson.core
jackson-core
- 2.15.2
+ ${jackson-annotations.version}
com.fasterxml.jackson.core
jackson-annotations
- 2.15.2
+ ${jackson-annotations.version}
org.projectlombok
@@ -429,6 +440,11 @@
${lombok.version}
provided
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-yaml
+ ${jackson-dataformat-yaml.version}
+
org.apache.commons
commons-lang3
@@ -438,6 +454,17 @@
io.confluent
kafka-schema-registry-client
${kafka-schema-registry-client.version}
+
+
+ com.google.guava
+ guava
+
+
+
+
+ com.google.guava
+ guava
+ 32.0.1-jre
io.confluent
@@ -458,12 +485,32 @@
com.github.everit-org.json-schema
org.everit.json.schema
+
+ org.jetbrains.kotlin
+ kotlin-stdlib
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib
+ 1.9.0
+
io.confluent
kafka-protobuf-serializer
${kafka-schema-registry-client.version}
+
+
+ com.google.code.gson
+ gson
+
+
+
+
+ com.google.code.gson
+ gson
+ 2.10.1
io.apicurio
@@ -491,6 +538,26 @@
apicurio-registry-serdes-protobuf-serde
${apicurio-registry.version}
+
+ org.json
+ json
+ 20231013
+
+
+ com.charleskorn.kaml
+ kaml
+ 0.53.0
+
+
+ com.squareup.okio
+ okio
+ 3.4.0
+
+
+ com.squareup.okhttp3
+ okhttp
+ 5.0.0-alpha.11
+
io.apicurio
apicurio-registry-utils-serde
@@ -499,28 +566,23 @@
org.apache.avro
avro-protobuf
- 1.11.2
+ 1.11.3
com.github.os72
protobuf-dynamic
1.0.1
-
- com.squareup.wire
- wire-java-generator
- 4.0.1
- runtime
-
+
com.google.api.grpc
proto-google-common-protos
- 2.24.0
+ 2.30.0
com.google.protobuf
protobuf-java
- 3.24.3
+ 3.25.1
org.slf4j
@@ -552,6 +614,12 @@
com.github.everit-org.json-schema
org.everit.json.schema
1.14.2
+
+
+ commons-collections
+ commons-collections
+
+
@@ -629,7 +697,7 @@
com.github.tomakehurst
- wiremock-jre8
+ wiremock
${wiremock.version}
test
@@ -665,13 +733,17 @@
+
+ jitpack.io
+ https://jitpack.io
+
confluent
https://packages.confluent.io/maven/
- jitpack.io
- https://jitpack.io
+ central
+ https://repo1.maven.org/maven2/
@@ -690,7 +762,7 @@
org.apache.maven.plugins
maven-checkstyle-plugin
- 3.1.2
+ 3.3.0
com.puppycrawl.tools
@@ -725,7 +797,7 @@
com.github.ekryd.sortpom
sortpom-maven-plugin
- 3.0.0
+ 3.3.0
@@ -738,7 +810,7 @@
org.apache.maven.plugins
maven-compiler-plugin
- 3.8.1
+ 3.9.0
true
true
@@ -757,7 +829,7 @@
cobertura-maven-plugin
2.7
-
+
xml
@@ -828,7 +900,7 @@
org.apache.maven.plugins
maven-shade-plugin
- 3.2.4
+ 3.3.0
diff --git a/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java b/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java
new file mode 100644
index 00000000..59484f3d
--- /dev/null
+++ b/src/main/java/com/sngular/kloadgen/common/tools/ApiTool.java
@@ -0,0 +1,286 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package com.sngular.kloadgen.common.tools;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.IteratorUtils;
+import org.apache.commons.collections4.Transformer;
+import org.apache.commons.lang3.StringUtils;
+
+public final class ApiTool {
+
+ public static final String FORMAT = "format";
+ public static final String ALL_OF = "allOf";
+ public static final String ANY_OF = "anyOf";
+ public static final String ONE_OF = "oneOf";
+ public static final String COMPONENTS = "components";
+ public static final String SCHEMAS = "schemas";
+
+ public static final String MESSAGES = "messages";
+ public static final String REQUIRED = "required";
+
+ public static final String PARAMETERS = "parameters";
+
+ public static final String RESPONSES = "responses";
+
+ private ApiTool() {
+ }
+
+ public static JsonNode findNodeValue(final JsonNode node, final String valueName) {
+ return node.findValue(valueName);
+ }
+
+ public static String getType(final JsonNode schema) {
+ return hasType(schema) ? getNodeAsString(schema, "type") : "";
+ }
+
+ public static Iterator> getProperties(final JsonNode schema) {
+ return getNode(schema, "properties").fields();
+ }
+
+ public static String getRefValue(final JsonNode schema) {
+ return getNode(schema, "$ref").textValue();
+ }
+
+ public static JsonNode getAdditionalProperties(final JsonNode schema) {
+ return getNode(schema, "additionalProperties");
+ }
+
+ public static String getFormat(final JsonNode schema) {
+ return getNodeAsString(schema, FORMAT);
+ }
+
+ public static JsonNode getAllOf(final JsonNode schema) {
+ return getNode(schema, ALL_OF);
+ }
+
+ public static JsonNode getAnyOf(final JsonNode schema) {
+ return getNode(schema, ANY_OF);
+ }
+
+ public static JsonNode getOneOf(final JsonNode schema) {
+ return getNode(schema, ONE_OF);
+ }
+
+ public static JsonNode getNode(final JsonNode schema, final String nodeName) {
+ return schema.get(nodeName);
+ }
+
+ public static String getNodeAsString(final JsonNode schema, final String nodeName) {
+ return hasNode(schema, nodeName) ? getNode(schema, nodeName).textValue() : null;
+ }
+
+ public static boolean getNodeAsBoolean(final JsonNode schema, final String nodeName) {
+ return hasNode(schema, nodeName) && getNode(schema, nodeName).booleanValue();
+ }
+
+ public static Iterator> getFieldIterator(final JsonNode schema) {
+ return Objects.nonNull(schema) ? schema.fields() : IteratorUtils.emptyIterator();
+ }
+
+ public static String getName(final JsonNode node) {
+ return hasNode(node, "name") ? getNodeAsString(node, "name") : node.textValue();
+ }
+
+ public static List getEnumValues(final JsonNode schema) {
+ return new ArrayList<>(CollectionUtils.collect(
+ IteratorUtils.toList(schema.get("enum").elements()),
+ getTextValue()));
+ }
+
+ public static JsonNode getItems(final JsonNode schema) {
+ return getNode(schema, "items");
+ }
+
+ public static Map getComponentSchemas(final JsonNode openApi) {
+ return getSchemas(openApi, SCHEMAS);
+ }
+
+ public static Map getComponentMessages(final JsonNode openApi) {
+ return getSchemas(openApi, MESSAGES);
+ }
+
+ public static Map getParameterSchemas(final JsonNode openApi) {
+ return getSchemas(openApi, PARAMETERS);
+ }
+
+ public static Map getResponseSchemas(final JsonNode openApi) {
+
+ return getSchemas(openApi, RESPONSES);
+ }
+
+ public static Map getSchemas(final JsonNode openApi, final String schemaType) {
+ final var schemasMap = new HashMap();
+
+ if (hasNode(openApi, COMPONENTS)) {
+ final var components = getNode(openApi, COMPONENTS);
+ if (hasNode(components, schemaType)) {
+ final var schemas = getNode(components, schemaType);
+ final var schemasIt = schemas.fieldNames();
+ schemasIt.forEachRemaining(name -> schemasMap.put(schemaType + "/" + name, getNode(schemas, name)));
+ }
+ }
+
+ return schemasMap;
+ }
+
+ public static Map getComponentSecuritySchemes(final JsonNode openApi) {
+ final var schemasMap = new HashMap();
+
+ if (hasNode(openApi, COMPONENTS)) {
+ final var components = getNode(openApi, COMPONENTS);
+ if (hasNode(components, "securitySchemes")) {
+ getNode(components, "securitySchemes").fields().forEachRemaining(schema -> schemasMap.put(schema.getKey(), schema.getValue()));
+ }
+ }
+
+ return schemasMap;
+ }
+
+ public static String getNumberType(final JsonNode schema) {
+ final String type;
+ if (hasType(schema)) {
+ type = switch (getType(schema)) {
+ case TypeConstants.DOUBLE -> TypeConstants.DOUBLE;
+ case TypeConstants.FLOAT -> TypeConstants.FLOAT;
+ case TypeConstants.NUMBER -> TypeConstants.NUMBER;
+ case TypeConstants.INT_64 -> TypeConstants.INT_64;
+ case TypeConstants.INT_32 -> TypeConstants.INT_32;
+ default -> TypeConstants.INTEGER;
+ };
+ } else {
+ type = TypeConstants.INTEGER;
+ }
+ return type;
+ }
+
+ public static boolean hasItems(final JsonNode schema) {
+ return hasNode(schema, "items");
+ }
+
+ public static boolean hasNode(final JsonNode schema, final String nodeName) {
+ return Objects.nonNull(schema) && schema.has(nodeName);
+ }
+
+ public static boolean hasField(final JsonNode schema, final String... fieldNameArray) {
+ final var nodeNamesList = Arrays.asList(fieldNameArray);
+ return StringUtils.isNotEmpty(IteratorUtils.find(schema.fieldNames(), nodeNamesList::contains));
+ }
+
+ public static boolean hasRequired(final JsonNode schema) {
+ return hasNode(schema, REQUIRED);
+ }
+
+ public static boolean hasType(final JsonNode schema) {
+ return hasNode(schema, "type");
+ }
+
+ public static boolean hasRef(final JsonNode schema) {
+ return hasNode(schema, "$ref");
+ }
+
+ public static boolean hasProperties(final JsonNode schema) {
+ return hasNode(schema, "properties");
+ }
+
+ public static boolean hasContent(final JsonNode schema) {
+ return hasNode(schema, "content");
+ }
+
+ public static boolean hasAdditionalProperties(final JsonNode schema) {
+ return hasNode(schema, "additionalProperties");
+ }
+
+ public static boolean hasFormat(final JsonNode schema) {
+ return hasNode(schema, "format");
+ }
+
+ public static boolean isObject(final JsonNode schema) {
+ return hasType(schema) && TypeConstants.OBJECT.equalsIgnoreCase(getType(schema));
+ }
+
+ public static boolean isArray(final JsonNode schema) {
+ return hasType(schema) && TypeConstants.ARRAY.equalsIgnoreCase(getType(schema));
+ }
+
+ public static boolean isComposed(final JsonNode schema) {
+ return ApiTool.hasField(schema, ANY_OF, ALL_OF, ONE_OF);
+ }
+
+ public static boolean isString(final JsonNode schema) {
+ return hasType(schema) && TypeConstants.STRING.equalsIgnoreCase(getType(schema));
+ }
+
+ public static boolean isBoolean(final JsonNode schema) {
+ return hasType(schema) && TypeConstants.BOOLEAN.equalsIgnoreCase(getType(schema));
+ }
+
+ public static boolean isNumber(final JsonNode schema) {
+ return hasType(schema)
+ && (TypeConstants.INTEGER.equalsIgnoreCase(getType(schema))
+ || TypeConstants.NUMBER.equalsIgnoreCase(getType(schema))
+ || TypeConstants.INT_64.equalsIgnoreCase(getType(schema))
+ || TypeConstants.INT_32.equalsIgnoreCase(getType(schema)));
+ }
+
+ public static boolean isEnum(final JsonNode schema) {
+ return schema.has("enum");
+ }
+
+ public static boolean isAllOf(final JsonNode schema) {
+ return hasNode(schema, ALL_OF);
+ }
+
+ public static boolean isAnyOf(final JsonNode schema) {
+ return hasNode(schema, ANY_OF);
+ }
+
+ public static boolean isOneOf(final JsonNode schema) {
+ return hasNode(schema, ONE_OF);
+ }
+
+ public static boolean isDateTime(final JsonNode schema) {
+ final boolean isDateTime;
+ if (hasType(schema) && TypeConstants.STRING.equalsIgnoreCase(getType(schema))) {
+ if (hasNode(schema, FORMAT)) {
+ isDateTime = "date".equalsIgnoreCase(getNode(schema, FORMAT).textValue())
+ || "date-time".equalsIgnoreCase(getNode(schema, FORMAT).textValue());
+ } else {
+ isDateTime = false;
+ }
+ } else {
+ isDateTime = false;
+ }
+ return isDateTime;
+ }
+
+ public static boolean checkIfRequired(final JsonNode schema, final String fieldName) {
+ boolean isRequired = false;
+ if (hasNode(schema, REQUIRED)) {
+ final var fieldIt = getNode(schema, REQUIRED).elements();
+ while (fieldIt.hasNext() && !isRequired) {
+ isRequired = fieldName.equalsIgnoreCase(fieldIt.next().textValue());
+ }
+ }
+ return isRequired;
+ }
+
+ private static Transformer getTextValue() {
+ return JsonNode::asText;
+ }
+
+}
diff --git a/src/main/java/com/sngular/kloadgen/common/tools/MapperUtil.java b/src/main/java/com/sngular/kloadgen/common/tools/MapperUtil.java
new file mode 100644
index 00000000..32b8b64a
--- /dev/null
+++ b/src/main/java/com/sngular/kloadgen/common/tools/MapperUtil.java
@@ -0,0 +1,136 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package com.sngular.kloadgen.common.tools;
+
+import java.util.Objects;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.apache.commons.lang3.StringUtils;
+
+public class MapperUtil {
+
+ public static final String INTEGER = "integer";
+
+ public static final String DOUBLE = "double";
+
+ public static final String FLOAT = "float";
+
+ public static final String NUMBER = "number";
+
+ public static final String INT_64 = "int64";
+
+ public static final String LONG = "long";
+
+ public static final String BIG_DECIMAL = "bigDecimal";
+
+ public static final String REF = "$ref";
+
+ private static final String DIVISOR = "([./])";
+
+ private MapperUtil() {}
+
+ public static String getSimpleType(final JsonNode schema, final String prefix, final String suffix) {
+ String type = schema.textValue();
+ if (schema.has("type")) {
+ type = schema.get("type").textValue();
+ String format = null;
+ if ("string".equalsIgnoreCase(type)) {
+ type = "String";
+ }
+ if (schema.has("format")) {
+ format = schema.get("format").textValue();
+ }
+ if (NUMBER.equalsIgnoreCase(type)) {
+ if (FLOAT.equalsIgnoreCase(format)) {
+ type = FLOAT;
+ } else if (DOUBLE.equalsIgnoreCase(format)) {
+ type = DOUBLE;
+ } else {
+ type = BIG_DECIMAL;
+ }
+ } else if (INTEGER.equalsIgnoreCase(type)) {
+ if (INT_64.equalsIgnoreCase(format)) {
+ type = LONG;
+ } else {
+ type = INTEGER;
+ }
+ }
+ } else if (schema.has(REF)) {
+ type = getRef(schema, prefix, suffix);
+ }
+ return type;
+ }
+
+ public static String getRef(final JsonNode schema, final String prefix, final String suffix) {
+ return getPojoName(getRefClass(schema), prefix, suffix);
+ }
+
+ public static String getLongRefClass(final JsonNode schema) {
+ final String[] pathObjectRef = getStrings(schema);
+ return pathObjectRef[pathObjectRef.length - 2] + "/" + pathObjectRef[pathObjectRef.length - 1];
+ }
+
+ private static String[] getStrings(final JsonNode schema) {
+ return splitName(schema.get(REF).textValue());
+ }
+
+ public static String getRefClass(final JsonNode schema) {
+ final String[] pathObjectRef = getStrings(schema);
+ return pathObjectRef[pathObjectRef.length - 1];
+ }
+
+ public static String getTypeMap(final JsonNode mapSchema, final String prefix, final String suffix) {
+ var typeMap = "";
+ final var mapNode = mapSchema.get("additionalProperties");
+ final var mapValueType = mapNode.findPath("type");
+ typeMap = getCollectionType(mapNode, mapValueType, prefix, suffix);
+ return typeMap;
+ }
+
+ public static String getTypeArray(final JsonNode array, final String prefix, final String suffix) {
+ var typeArray = "";
+ final var arrayNode = array.get("items");
+ final JsonNode mapValueType;
+ if (arrayNode.has("type")) {
+ mapValueType = arrayNode.get("type");
+ } else {
+ mapValueType = arrayNode.get(REF);
+ }
+ typeArray = getCollectionType(arrayNode, mapValueType, prefix, suffix);
+ return typeArray;
+ }
+
+ private static String getCollectionType(final JsonNode mapNode, final JsonNode mapValueType, final String prefix, final String suffix) {
+ var typeMap = mapValueType.textValue();
+ if (!typeMap.contains("#")) {
+ if ("string".equalsIgnoreCase(mapValueType.textValue())) {
+ typeMap = "String";
+ } else if (INTEGER.equalsIgnoreCase(mapValueType.textValue())) {
+ typeMap = "Integer";
+ } else {
+ typeMap = mapValueType.textValue();
+ }
+ } else {
+ final var valueSchema = mapNode.findPath(REF);
+ if (Objects.nonNull(valueSchema)) {
+ getRef(valueSchema, prefix, suffix);
+ }
+ }
+ return typeMap;
+ }
+
+ public static String getPojoName(final String namePojo, final String prefix, final String suffix) {
+ return StringUtils.defaultIfBlank(prefix, "")
+ + StringUtils.capitalize(namePojo)
+ + StringUtils.defaultIfBlank(suffix, "");
+ }
+
+ public static String[] splitName(final String name) {
+ return name.split(DIVISOR);
+ }
+
+}
diff --git a/src/main/java/com/sngular/kloadgen/common/tools/TypeConstants.java b/src/main/java/com/sngular/kloadgen/common/tools/TypeConstants.java
new file mode 100644
index 00000000..e02a7e59
--- /dev/null
+++ b/src/main/java/com/sngular/kloadgen/common/tools/TypeConstants.java
@@ -0,0 +1,35 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package com.sngular.kloadgen.common.tools;
+
+public final class TypeConstants {
+
+ public static final String NUMBER = "number";
+
+ public static final String BOOLEAN = "boolean";
+
+ public static final String OBJECT = "object";
+
+ public static final String ARRAY = "array";
+
+ public static final String INTEGER = "integer";
+
+ public static final String DOUBLE = "double";
+
+ public static final String FLOAT = "float";
+
+ public static final String LONG = "long";
+
+ public static final String STRING = "string";
+
+ public static final String INT_32 = "int32";
+
+ public static final String INT_64 = "int64";
+
+ private TypeConstants() {
+ }
+}
diff --git a/src/main/java/com/sngular/kloadgen/config/kafkaheaders/KafkaHeadersConfigElement.java b/src/main/java/com/sngular/kloadgen/config/kafkaheaders/KafkaHeadersConfigElement.java
index 5878bd68..5698d1dc 100644
--- a/src/main/java/com/sngular/kloadgen/config/kafkaheaders/KafkaHeadersConfigElement.java
+++ b/src/main/java/com/sngular/kloadgen/config/kafkaheaders/KafkaHeadersConfigElement.java
@@ -32,7 +32,7 @@ public class KafkaHeadersConfigElement extends ConfigTestElement implements Test
private List kafkaHeaders;
@Override
- public final void iterationStart(final LoopIterationEvent iterEvent) {
+ public final void iterationStart(final LoopIterationEvent iteEvent) {
final JMeterContext context = getThreadContext();
diff --git a/src/main/java/com/sngular/kloadgen/config/keydeserialized/KeyDeserializedConfigElement.java b/src/main/java/com/sngular/kloadgen/config/keydeserialized/KeyDeserializedConfigElement.java
index 1d868bac..0cdfe368 100644
--- a/src/main/java/com/sngular/kloadgen/config/keydeserialized/KeyDeserializedConfigElement.java
+++ b/src/main/java/com/sngular/kloadgen/config/keydeserialized/KeyDeserializedConfigElement.java
@@ -4,12 +4,6 @@
* * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
-/*
- * This Source Code Form is subject to the terms of the Mozilla Public
- * * License, v. 2.0. If a copy of the MPL was not distributed with this
- * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
- */
-
package com.sngular.kloadgen.config.keydeserialized;
import java.util.List;
diff --git a/src/main/java/com/sngular/kloadgen/config/schemaregistry/SchemaRegistryConfigElementBeanInfo.java b/src/main/java/com/sngular/kloadgen/config/schemaregistry/SchemaRegistryConfigElementBeanInfo.java
index ad9072e6..e369f9fc 100644
--- a/src/main/java/com/sngular/kloadgen/config/schemaregistry/SchemaRegistryConfigElementBeanInfo.java
+++ b/src/main/java/com/sngular/kloadgen/config/schemaregistry/SchemaRegistryConfigElementBeanInfo.java
@@ -11,6 +11,7 @@
import com.sngular.kloadgen.model.PropertyMapping;
import com.sngular.kloadgen.property.editor.SchemaRegistryConfigPropertyEditor;
import com.sngular.kloadgen.property.editor.SchemaRegistryNamePropertyEditor;
+import com.sngular.kloadgen.sampler.gui.DefaultPropertiesHelper;
import com.sngular.kloadgen.util.SchemaRegistryKeyHelper;
import org.apache.jmeter.testbeans.BeanInfoSupport;
import org.apache.jmeter.testbeans.gui.TableEditor;
diff --git a/src/main/java/com/sngular/kloadgen/config/schemaregistry/SchemaRegistryConfigElementValue.java b/src/main/java/com/sngular/kloadgen/config/schemaregistry/SchemaRegistryConfigElementValue.java
index 8aeae711..7ee3078c 100644
--- a/src/main/java/com/sngular/kloadgen/config/schemaregistry/SchemaRegistryConfigElementValue.java
+++ b/src/main/java/com/sngular/kloadgen/config/schemaregistry/SchemaRegistryConfigElementValue.java
@@ -1,3 +1,9 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
package com.sngular.kloadgen.config.schemaregistry;
public final class SchemaRegistryConfigElementValue {
diff --git a/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java
new file mode 100644
index 00000000..d6eda7a7
--- /dev/null
+++ b/src/main/java/com/sngular/kloadgen/extractor/ApiExtractor.java
@@ -0,0 +1,33 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package com.sngular.kloadgen.extractor;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.sngular.kloadgen.extractor.model.AsyncApiFile;
+import com.sngular.kloadgen.extractor.model.AsyncApiSR;
+import com.sngular.kloadgen.extractor.model.AsyncApiSchema;
+import com.sngular.kloadgen.extractor.model.AsyncApiServer;
+
+public interface ApiExtractor {
+
+ AsyncApiFile processFile(final File apiFile);
+
+ AsyncApiFile processNode(final JsonNode apiFile);
+
+ Map getBrokerData(final AsyncApiFile asyncApiFile);
+
+ List getSchemaRegistryData(final AsyncApiFile asyncApiFile);
+
+ AsyncApiSchema getSchemaData(final AsyncApiFile asyncApiFile, final String topic);
+
+ Map getSchemaDataMap(final AsyncApiFile asyncApiFile);
+
+}
diff --git a/src/main/java/com/sngular/kloadgen/extractor/SchemaExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/SchemaExtractor.java
index 034e5e89..c356bd24 100644
--- a/src/main/java/com/sngular/kloadgen/extractor/SchemaExtractor.java
+++ b/src/main/java/com/sngular/kloadgen/extractor/SchemaExtractor.java
@@ -1,3 +1,9 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
package com.sngular.kloadgen.extractor;
import java.io.IOException;
@@ -10,7 +16,7 @@
import com.sngular.kloadgen.common.SchemaRegistryEnum;
import com.sngular.kloadgen.extractor.extractors.ExtractorFactory;
import com.sngular.kloadgen.model.FieldValueMapping;
-import com.sngular.kloadgen.parsedschema.ParsedSchema;
+import com.sngular.kloadgen.parsedschema.AbstractParsedSchema;
import lombok.Getter;
import org.apache.commons.lang3.tuple.Pair;
@@ -30,7 +36,7 @@ public static Pair> flatPropertiesList(final Str
return ExtractorFactory.flatPropertiesList(subjectName);
}
- public static List flatPropertiesList(final ParsedSchema parserSchema) {
+ public static List flatPropertiesList(final AbstractParsedSchema> parserSchema) {
return ExtractorFactory.getExtractor(parserSchema.schemaType()).processSchema(parserSchema, SchemaRegistryEnum.CONFLUENT);
}
diff --git a/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java b/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java
new file mode 100644
index 00000000..d0d05263
--- /dev/null
+++ b/src/main/java/com/sngular/kloadgen/extractor/asyncapi/AsyncApiExtractorImpl.java
@@ -0,0 +1,330 @@
+package com.sngular.kloadgen.extractor.asyncapi;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Set;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
+import com.sngular.kloadgen.common.tools.ApiTool;
+import com.sngular.kloadgen.common.tools.MapperUtil;
+import com.sngular.kloadgen.exception.KLoadGenException;
+import com.sngular.kloadgen.extractor.ApiExtractor;
+import com.sngular.kloadgen.extractor.model.AsyncApiFile;
+import com.sngular.kloadgen.extractor.model.AsyncApiSR;
+import com.sngular.kloadgen.extractor.model.AsyncApiSchema;
+import com.sngular.kloadgen.extractor.model.AsyncApiServer;
+import com.sngular.kloadgen.model.ConstraintTypeEnum;
+import com.sngular.kloadgen.model.FieldValueMapping;
+import org.apache.commons.lang3.StringUtils;
+
+public class AsyncApiExtractorImpl implements ApiExtractor {
+
+ private static final Set COMPLEX_TYPES = Set.of("record", "array");
+ private static final String ERROR_WRONG_ASYNC_API_SCHEMA = "Wrong AsyncApi Schema";
+
+ private static final String SERVERS = "servers";
+
+ private static final String CHANNELS = "channels";
+
+ private final ObjectMapper om = new ObjectMapper(new YAMLFactory());
+
+ @Override
+ public final AsyncApiFile processFile(final File apiFile) {
+ final AsyncApiFile asyncApiFile;
+ try {
+ final JsonNode openApi = om.readTree(apiFile);
+ asyncApiFile = processNode(openApi);
+ } catch (final IOException e) {
+ throw new KLoadGenException(ERROR_WRONG_ASYNC_API_SCHEMA, e);
+ }
+
+ return asyncApiFile;
+ }
+
+ @Override
+ public final AsyncApiFile processNode(final JsonNode apiFile) {
+ return AsyncApiFile.builder()
+ .asyncApiFileNode(apiFile)
+ .apiServerMap(nodeToApServer(ApiTool.getNode(apiFile, SERVERS)))
+ .apiSchemaList(nodeToSchema(apiFile))
+ .build();
+ }
+
+ private Map nodeToSchema(final JsonNode openApi) {
+ final var channels = ApiTool.getNode(openApi, CHANNELS);
+ final var schemaList = new HashMap();
+ final Map totalSchemas = new HashMap<>(ApiTool.getComponentSchemas(openApi));
+ totalSchemas.putAll(ApiTool.getComponentMessages(openApi));
+ channels
+ .fields()
+ .forEachRemaining(channel ->
+ schemaList.put(channel.getKey(),
+ mapNodeToSchema(totalSchemas, channel.getKey(), channel.getValue())));
+ return schemaList;
+ }
+
+ private AsyncApiSchema mapNodeToSchema(final Map components, final String topic, final JsonNode node) {
+ final var antiLoopList = new ArrayList();
+ final var builder = AsyncApiSchema.builder();
+ builder.topicName(topic);
+ final var message = ApiTool.findNodeValue(node, "message");
+ if (ApiTool.hasNode(message, "bindings")) {
+ builder.key(true);
+ // builder.keyType(ApiTool.findValue(message, "key"));
+ }
+ builder.model(messageToFieldList(message, components, antiLoopList));
+ return builder.build();
+ }
+
+ private List messageToFieldList(final JsonNode message, final Map components, final List antiLoopList) {
+ var payload = ApiTool.getNode(message, "payload");
+ if (ApiTool.hasRef(message)) {
+ payload = ApiTool.getNode(solveRef(message, components, antiLoopList, "messages"), "payload");
+ } else if (!ApiTool.hasNode(message, "payload")) {
+ throw new KLoadGenException("AsyncApi format still not supported");
+ }
+
+
+ return extractFieldList(payload, components, antiLoopList);
+ }
+
+ private List extractFieldList(final JsonNode payload, final Map components, final List antiLoopList) {
+ var finalPayload = payload;
+ if (ApiTool.hasRef(payload)) {
+ final var payloadPath = MapperUtil.splitName(ApiTool.getRefValue(payload));
+ final String objectName = payloadPath[payloadPath.length - 1];
+ if (!antiLoopList.contains(objectName)) {
+ finalPayload = components.get("schemas/" + objectName);
+ antiLoopList.add(objectName);
+ }
+ }
+ if (!ApiTool.hasProperties(finalPayload)) {
+ throw new KLoadGenException("Wrong Payload for message ");
+ }
+ return new ArrayList<>(processPayload(finalPayload, "", components, antiLoopList));
+ }
+
+ private List processPayload(final JsonNode finalPayload, final String root, final Map components, final List antiLoopList) {
+ final var fieldList = new ArrayList();
+ if (ApiTool.hasRef(finalPayload)) {
+ fieldList.addAll(processPayload(solveRef(finalPayload, components, antiLoopList, "schemas"), root, components, antiLoopList));
+ } else if (ApiTool.hasAdditionalProperties(finalPayload)) {
+ fieldList.addAll(processMap(finalPayload, root, components, antiLoopList));
+ } else if (ApiTool.hasProperties(finalPayload)) {
+ for (Iterator> it = ApiTool.getProperties(finalPayload); it.hasNext();) {
+ final var property = it.next();
+ final var propertyDef = property.getValue();
+ final var propertyName = calculateName(property.getKey(), root);
+ if (ApiTool.hasRef(propertyDef)) {
+ final var solvedPayload = solveRef(propertyDef, components, antiLoopList, "schemas");
+ if (Objects.nonNull(solvedPayload)) {
+ fieldList.addAll(processPayload(solvedPayload, propertyName, components, antiLoopList));
+ }
+ } else if (COMPLEX_TYPES.contains(ApiTool.getType(propertyDef)) || ApiTool.hasAdditionalProperties(propertyDef)) {
+ fieldList.addAll(calculatePayload(propertyDef, propertyName, components, antiLoopList));
+ } else {
+ fieldList.add(FieldValueMapping
+ .builder()
+ .fieldName(propertyName)
+ .fieldType(getType(propertyDef))
+ .fieldValueList(hasValues(propertyDef))
+ .required(ApiTool.checkIfRequired(finalPayload, property.getKey()))
+ .constraints(getConstraints(propertyDef))
+ .build());
+ }
+ }
+ } else {
+ fieldList.add(FieldValueMapping
+ .builder()
+ .fieldName(calculateName(null, root))
+ .fieldType(getType(finalPayload))
+ .fieldValueList(hasValues(finalPayload))
+ .required(true)
+ .constraints(getConstraints(finalPayload))
+ .build());
+ }
+ return fieldList;
+ }
+
+ private String getType(final JsonNode finalPayload) {
+ String type = ApiTool.getType(finalPayload);
+ if (ApiTool.hasFormat(finalPayload)) {
+ type = switch (ApiTool.getFormat(finalPayload)) {
+ case "date-time" -> "datetime";
+ case "int64" -> "long";
+ case "double" -> "double";
+ case "date" -> "date";
+ case "string" -> ApiTool.isEnum(finalPayload) ? "enum" : "string";
+ default -> ApiTool.getType(finalPayload);
+ };
+
+ }
+ return type;
+ }
+
+ private Map getConstraints(final JsonNode finalPayload) {
+ final Map constraints = new EnumMap<>(ConstraintTypeEnum.class);
+ if (ApiTool.hasNode(finalPayload, "minLength")) {
+ constraints.put(ConstraintTypeEnum.MIN_LENGTH, ApiTool.getNodeAsString(finalPayload, "minLength"));
+ }
+ if (ApiTool.hasNode(finalPayload, "maxLength")) {
+ constraints.put(ConstraintTypeEnum.MAX_LENGTH, ApiTool.getNodeAsString(finalPayload, "minLength"));
+ }
+ if (ApiTool.hasNode(finalPayload, "minimum")) {
+ constraints.put(ConstraintTypeEnum.MINIMUM_VALUE, ApiTool.getNodeAsString(finalPayload, "minimum"));
+ }
+ if (ApiTool.hasNode(finalPayload, "maximum")) {
+ constraints.put(ConstraintTypeEnum.MAXIMUM_VALUE, ApiTool.getNodeAsString(finalPayload, "maximum"));
+ }
+ if (ApiTool.hasNode(finalPayload, "exclusiveMinimum")) {
+ constraints.put(ConstraintTypeEnum.EXCLUDED_MINIMUM_VALUE, ApiTool.getNodeAsString(finalPayload, "exclusiveMinimum"));
+ }
+ if (ApiTool.hasNode(finalPayload, "exclusiveMaximum")) {
+ constraints.put(ConstraintTypeEnum.EXCLUDED_MAXIMUM_VALUE, ApiTool.getNodeAsString(finalPayload, "exclusiveMaximum"));
+ }
+ if (ApiTool.hasNode(finalPayload, "multipleOf")) {
+ constraints.put(ConstraintTypeEnum.MULTIPLE_OF, ApiTool.getNodeAsString(finalPayload, "multipleOf"));
+ }
+
+ return constraints;
+ }
+
+ private String hasValues(final JsonNode propertyDef) {
+ String values = null;
+ if (ApiTool.isEnum(propertyDef)) {
+ values = String.join(",", ApiTool.getEnumValues(propertyDef));
+ }
+ return values;
+ }
+
+ private List calculatePayload(final JsonNode propertyDef, final String root, final Map components, final List antiLoopList) {
+ final var fieldList = new ArrayList();
+ if (!ApiTool.hasAdditionalProperties(propertyDef)) {
+ switch (ApiTool.getType(propertyDef)) {
+ case "object" -> fieldList.addAll(processPayload(propertyDef, root, components, antiLoopList));
+ case "array" -> fieldList.addAll(processArray(propertyDef, root, components, antiLoopList));
+ default -> {
+ }
+ }
+ } else {
+ fieldList.addAll(processMap(propertyDef, root, components, antiLoopList));
+ }
+ return fieldList;
+ }
+
+ private List processArray(final JsonNode propertyDef, final String root, final Map components, final List antiLoopList) {
+ final List fieldList = new ArrayList<>();
+
+ if (ApiTool.hasItems(propertyDef)) {
+ final var itemNode = ApiTool.getItems(propertyDef);
+ if (ApiTool.hasRef(itemNode)) {
+ fieldList.addAll(processPayload(itemNode, root + "[]", components, antiLoopList));
+ } else {
+ switch (ApiTool.getType(itemNode)) {
+ case "object" -> fieldList.addAll(processPayload(itemNode, root + "[]", components, antiLoopList));
+ case "string", "number", "integer", "boolean" -> fieldList.add(FieldValueMapping
+ .builder()
+ .fieldName(root + "[]")
+ .fieldType(ApiTool.getType(itemNode) + "-array")
+ .build());
+
+ default -> throw new KLoadGenException("Unexpected value: " + ApiTool.getType(itemNode));
+ }
+ }
+ } else {
+ throw new KLoadGenException(String.format("Wrong Array Definition for %s", root));
+ }
+ return fieldList;
+ }
+
+ private List processMap(final JsonNode propertyDef, final String root, final Map components, final List antiLoopList) {
+ final List fieldList = new ArrayList<>();
+
+ if (ApiTool.hasAdditionalProperties(propertyDef)) {
+ final var itemNode = ApiTool.getAdditionalProperties(propertyDef);
+
+ switch (ApiTool.getType(itemNode)) {
+ case "object" -> fieldList.addAll(processPayload(itemNode, root + "[:]", components, antiLoopList));
+ case "string", "number", "integer", "boolean" -> fieldList.add(FieldValueMapping
+ .builder()
+ .fieldName(root + "[:]")
+ .fieldType(ApiTool.getType(itemNode) + "-map")
+ .build());
+ default -> throw new KLoadGenException("Unexpected value: " + ApiTool.getType(itemNode));
+ }
+ } else {
+ throw new KLoadGenException(String.format("Wrong Array Definition for %s", root));
+ }
+ return fieldList;
+ }
+
+ private String calculateName(final String propertyName, final String root) {
+ final String finalName;
+ if (Objects.nonNull(propertyName)) {
+ if (StringUtils.isEmpty(root)) {
+ finalName = propertyName;
+ } else {
+ finalName = root + "." + propertyName;
+ }
+ } else {
+ finalName = root.substring(root.lastIndexOf("."));
+ }
+ return finalName;
+ }
+
+ private Map nodeToApServer(final JsonNode node) {
+ final var serverList = new HashMap();
+ node.fields().forEachRemaining(server -> serverList.put(server.getKey(), mapNodeToServer(server.getKey(), server.getValue())));
+ return serverList;
+ }
+
+ private JsonNode solveRef(final JsonNode message, final Map components, final List antiLoopList, final String schemaType) {
+ JsonNode payload = null;
+ final var payloadPath = MapperUtil.splitName(ApiTool.getRefValue(message));
+ final var objectName = payloadPath[payloadPath.length - 1];
+ if (!antiLoopList.contains(objectName)) {
+ payload = components.get(schemaType + "/" + objectName);
+ antiLoopList.add(objectName);
+ }
+ return payload;
+ }
+
+ private AsyncApiServer mapNodeToServer(final String serverName, final JsonNode server) {
+ final var builder = AsyncApiServer.builder();
+ builder.name(serverName);
+ builder.url(ApiTool.getNodeAsString(server, "url"));
+ builder.protocol(ApiTool.getNodeAsString(server, "protocol"));
+ builder.description(ApiTool.getNodeAsString(server, "description"));
+ return builder.build();
+ }
+
+ @Override
+ public final Map getBrokerData(final AsyncApiFile asyncApiFile) {
+ return asyncApiFile.getApiServerMap();
+ }
+
+ @Override
+ public final List getSchemaRegistryData(final AsyncApiFile asyncApiFile) {
+ return asyncApiFile.getApiAsyncApiSRList();
+ }
+
+ @Override
+ public final AsyncApiSchema getSchemaData(final AsyncApiFile asyncApiFile, final String topic) {
+ return asyncApiFile.getApiSchemaList().get(topic);
+ }
+
+ @Override
+ public final Map getSchemaDataMap(final AsyncApiFile asyncApiFile) {
+ return asyncApiFile.getApiSchemaList();
+ }
+}
diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/Extractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/Extractor.java
index b67f7eaa..447e5161 100644
--- a/src/main/java/com/sngular/kloadgen/extractor/extractors/Extractor.java
+++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/Extractor.java
@@ -1,3 +1,9 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
package com.sngular.kloadgen.extractor.extractors;
import java.util.List;
diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java
index 3189f117..892ecb77 100644
--- a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java
+++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorFactory.java
@@ -1,8 +1,13 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
package com.sngular.kloadgen.extractor.extractors;
import java.util.ArrayList;
import java.util.List;
-import java.util.Objects;
import java.util.Properties;
import com.sngular.kloadgen.common.SchemaRegistryEnum;
@@ -12,12 +17,10 @@
import com.sngular.kloadgen.extractor.extractors.json.JsonExtractor;
import com.sngular.kloadgen.extractor.extractors.protobuf.ProtobufExtractor;
import com.sngular.kloadgen.model.FieldValueMapping;
-import com.sngular.kloadgen.parsedschema.ParsedSchema;
-import com.sngular.kloadgen.schemaregistry.adapter.impl.AbstractParsedSchemaAdapter;
-import com.sngular.kloadgen.schemaregistry.adapter.impl.ApicurioAbstractParsedSchemaMetadata;
import com.sngular.kloadgen.util.JMeterHelper;
import com.sngular.kloadgen.util.SchemaRegistryKeyHelper;
import org.apache.commons.lang3.EnumUtils;
+import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.jmeter.threads.JMeterContextService;
@@ -37,16 +40,14 @@ public static void configExtractorFactory(final AvroExtractor avroExtractor, fin
ExtractorFactory.protobufExtractor = protobufExtractor;
}
- public static ExtractorRegistry getExtractor(final String schemaType) {
+ public static ExtractorRegistry> getExtractor(final String schemaType) {
if (schemaType != null && EnumUtils.isValidEnum(SchemaTypeEnum.class, schemaType.toUpperCase())) {
- final ExtractorRegistry response = switch (SchemaTypeEnum.valueOf(schemaType.toUpperCase())) {
+ return switch (SchemaTypeEnum.valueOf(schemaType.toUpperCase())) {
case JSON -> jsonExtractor;
case AVRO -> avroExtractor;
case PROTOBUF -> protobufExtractor;
- default -> throw new KLoadGenException(String.format("Schema type not supported %s", schemaType));
};
- return response;
} else {
throw new KLoadGenException(String.format("Schema type not supported %s", schemaType));
}
@@ -56,20 +57,13 @@ public static Pair> flatPropertiesList(final Str
final Properties properties = JMeterContextService.getContext().getProperties();
final var schemaParsed = JMeterHelper.getParsedSchema(subjectName, properties);
final String registryName = properties.getProperty(SchemaRegistryKeyHelper.SCHEMA_REGISTRY_NAME);
- final AbstractParsedSchemaAdapter abstractParsedSchemaAdapter = schemaParsed.getParsedSchemaAdapter();
- final String schemaType = abstractParsedSchemaAdapter.getType();
+ final String schemaType = schemaParsed.getSchemaType();
final List attributeList = new ArrayList<>();
final SchemaRegistryEnum schemaRegistryEnum = SchemaRegistryEnum.valueOf(registryName.toUpperCase());
- final Object schema;
- if (Objects.nonNull(registryName)) {
- //TODO change parser
- schema = switch (schemaRegistryEnum) {
- case APICURIO -> ((ApicurioAbstractParsedSchemaMetadata) abstractParsedSchemaAdapter).getSchema();
- case CONFLUENT -> abstractParsedSchemaAdapter.getRawSchema();
- };
- attributeList.addAll(getExtractor(schemaType).processSchema(new ParsedSchema(schema), schemaRegistryEnum));
+ if (StringUtils.isNotEmpty(registryName)) {
+ attributeList.addAll(getExtractor(schemaType).processSchema(schemaParsed, schemaRegistryEnum));
}
return Pair.of(schemaType, attributeList);
}
diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorRegistry.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorRegistry.java
index 27026c59..1c61c373 100644
--- a/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorRegistry.java
+++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/ExtractorRegistry.java
@@ -1,14 +1,22 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
package com.sngular.kloadgen.extractor.extractors;
import java.util.List;
import com.sngular.kloadgen.common.SchemaRegistryEnum;
import com.sngular.kloadgen.model.FieldValueMapping;
+import com.sngular.kloadgen.parsedschema.AbstractParsedSchema;
+
+public interface ExtractorRegistry> {
-public interface ExtractorRegistry {
- List processSchema(final T schema, SchemaRegistryEnum registry);
+ List processSchema(final AbstractParsedSchema> schema, SchemaRegistryEnum registry);
- Object processSchema(final String fileContent);
+ T processSchema(final String fileContent);
List getSchemaNameList(final String schema, SchemaRegistryEnum registryEnum);
diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/SchemaExtractorUtil.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/SchemaExtractorUtil.java
index 4b512103..821be7e6 100644
--- a/src/main/java/com/sngular/kloadgen/extractor/extractors/SchemaExtractorUtil.java
+++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/SchemaExtractorUtil.java
@@ -1,3 +1,9 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
package com.sngular.kloadgen.extractor.extractors;
public final class SchemaExtractorUtil {
diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java
index d5589ac0..c78f8d59 100644
--- a/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java
+++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/avro/AvroExtractor.java
@@ -7,23 +7,25 @@
import com.sngular.kloadgen.extractor.extractors.Extractor;
import com.sngular.kloadgen.extractor.extractors.ExtractorRegistry;
import com.sngular.kloadgen.model.FieldValueMapping;
-import com.sngular.kloadgen.parsedschema.ParsedSchema;
+import com.sngular.kloadgen.parsedschema.AbstractParsedSchema;
+import com.sngular.kloadgen.parsedschema.AvroParsedSchema;
+import org.apache.avro.Schema;
-public class AvroExtractor implements ExtractorRegistry {
+public class AvroExtractor implements ExtractorRegistry {
- private static Map schemaRegistryMap = Map.of(SchemaRegistryEnum.CONFLUENT, new AvroConfluentExtractor(), SchemaRegistryEnum.APICURIO,
+ private static final Map SCHEMA_REGISTRY_MAP = Map.of(SchemaRegistryEnum.CONFLUENT, new AvroConfluentExtractor(), SchemaRegistryEnum.APICURIO,
new AvroApicurioExtractor());
- public final List processSchema(final ParsedSchema schema, final SchemaRegistryEnum registryEnum) {
- return schemaRegistryMap.get(registryEnum).processSchema(schema.rawSchema());
+ public final List processSchema(final AbstractParsedSchema> schema, final SchemaRegistryEnum registryEnum) {
+ return SCHEMA_REGISTRY_MAP.get(registryEnum).processSchema(schema.getSchema());
}
- public final ParsedSchema processSchema(final String fileContent) {
- return new ParsedSchema(fileContent, "AVRO");
+ public final AvroParsedSchema processSchema(final String fileContent) {
+ return new AvroParsedSchema(null, new Schema.Parser().parse(fileContent));
}
public final List getSchemaNameList(final String schema, final SchemaRegistryEnum registryEnum) {
- return schemaRegistryMap.get(registryEnum).getSchemaNameList(schema);
+ return SCHEMA_REGISTRY_MAP.get(registryEnum).getSchemaNameList(schema);
}
}
\ No newline at end of file
diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/json/JsonExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/json/JsonExtractor.java
index 80c6ba24..ca3ac322 100644
--- a/src/main/java/com/sngular/kloadgen/extractor/extractors/json/JsonExtractor.java
+++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/json/JsonExtractor.java
@@ -7,20 +7,21 @@
import com.sngular.kloadgen.extractor.extractors.Extractor;
import com.sngular.kloadgen.extractor.extractors.ExtractorRegistry;
import com.sngular.kloadgen.model.FieldValueMapping;
-import com.sngular.kloadgen.parsedschema.ParsedSchema;
+import com.sngular.kloadgen.parsedschema.AbstractParsedSchema;
+import com.sngular.kloadgen.parsedschema.JsonParsedSchema;
+public class JsonExtractor implements ExtractorRegistry {
-public class JsonExtractor implements ExtractorRegistry {
-
- private static final Map SCHEMA_REGISTRY_MAP = Map.of(SchemaRegistryEnum.CONFLUENT, new JsonDefaultExtractor(),
+ private static final Map> SCHEMA_REGISTRY_MAP = Map.of(SchemaRegistryEnum.CONFLUENT, new JsonDefaultExtractor(),
SchemaRegistryEnum.APICURIO, new JsonDefaultExtractor());
- public final List processSchema(final ParsedSchema schemaReceived, final SchemaRegistryEnum registryEnum) {
- return SCHEMA_REGISTRY_MAP.get(registryEnum).processSchema(schemaReceived.rawSchema().toString());
+ public final List processSchema(final AbstractParsedSchema> schemaReceived, final SchemaRegistryEnum registryEnum) {
+ return SCHEMA_REGISTRY_MAP.get(registryEnum).processSchema(schemaReceived.getRawSchema().toString());
}
- public final ParsedSchema processSchema(final String fileContent) {
- return new ParsedSchema(fileContent, "JSON");
+
+ public final JsonParsedSchema processSchema(final String fileContent) {
+ return new JsonParsedSchema(null, fileContent);
}
public final List getSchemaNameList(final String schema, final SchemaRegistryEnum registryEnum) {
diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtoBufConfluentExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtoBufConfluentExtractor.java
index 62f3b73c..ea73b9a6 100644
--- a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtoBufConfluentExtractor.java
+++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtoBufConfluentExtractor.java
@@ -4,14 +4,14 @@
import com.sngular.kloadgen.extractor.extractors.Extractor;
import com.sngular.kloadgen.model.FieldValueMapping;
-import com.sngular.kloadgen.parsedschema.ParsedSchema;
+import com.sngular.kloadgen.parsedschema.AbstractParsedSchema;
import com.squareup.wire.schema.internal.parser.ProtoFileElement;
import io.confluent.kafka.schemaregistry.protobuf.ProtobufSchema;
-public class ProtoBufConfluentExtractor extends AbstractProtoFileExtractor implements Extractor {
+public class ProtoBufConfluentExtractor extends AbstractProtoFileExtractor implements Extractor> {
- public final List processSchema(final ParsedSchema schemaReceived) {
- return processSchemaDefault((ProtoFileElement) schemaReceived.rawSchema());
+ public final List processSchema(final AbstractParsedSchema schemaReceived) {
+ return processSchemaDefault(schemaReceived.getRawSchema());
}
public final List getSchemaNameList(final String schema) {
diff --git a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufExtractor.java b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufExtractor.java
index 0133c261..d1944c11 100644
--- a/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufExtractor.java
+++ b/src/main/java/com/sngular/kloadgen/extractor/extractors/protobuf/ProtobufExtractor.java
@@ -8,19 +8,23 @@
import com.sngular.kloadgen.extractor.extractors.Extractor;
import com.sngular.kloadgen.extractor.extractors.ExtractorRegistry;
import com.sngular.kloadgen.model.FieldValueMapping;
-import com.sngular.kloadgen.parsedschema.ParsedSchema;
+import com.sngular.kloadgen.parsedschema.AbstractParsedSchema;
+import com.sngular.kloadgen.parsedschema.ProtobufParsedSchema;
+import com.squareup.wire.schema.Location;
+import com.squareup.wire.schema.internal.parser.ProtoParser;
-public class ProtobufExtractor implements ExtractorRegistry {
+public class ProtobufExtractor implements ExtractorRegistry {
private static final Map SCHEMA_REGISTRY_MAP = Map.of(SchemaRegistryEnum.CONFLUENT, new ProtoBufConfluentExtractor(),
SchemaRegistryEnum.APICURIO, new ProtoBufApicurioExtractor());
- public final List processSchema(final ParsedSchema schemaReceived, final SchemaRegistryEnum registryEnum) {
+ public final List processSchema(final AbstractParsedSchema> schemaReceived, final SchemaRegistryEnum registryEnum) {
return new ArrayList(SCHEMA_REGISTRY_MAP.get(registryEnum).processSchema(schemaReceived));
}
- public final ParsedSchema processSchema(final String fileContent) {
- return new ParsedSchema(fileContent, "PROTOBUF");
+ public final ProtobufParsedSchema processSchema(final String fileContent) {
+ final var protoDescriptor = new ProtoParser(Location.get("/"), fileContent.toCharArray());
+ return new ProtobufParsedSchema(null, protoDescriptor.readProtoFile());
}
public final List getSchemaNameList(final String schema, final SchemaRegistryEnum registryEnum) {
diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiAbstract.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiAbstract.java
new file mode 100644
index 00000000..c2b8c44e
--- /dev/null
+++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiAbstract.java
@@ -0,0 +1,20 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package com.sngular.kloadgen.extractor.model;
+
+import java.util.Collections;
+import java.util.Map;
+
+public interface AsyncApiAbstract {
+
+ Object[] getProperties();
+
+ default Map getPropertiesMap() {
+ return Collections.emptyMap();
+ }
+
+}
diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java
new file mode 100644
index 00000000..ea05aa49
--- /dev/null
+++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiFile.java
@@ -0,0 +1,31 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package com.sngular.kloadgen.extractor.model;
+
+import java.util.List;
+import java.util.Map;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import lombok.Builder;
+import lombok.Singular;
+import lombok.Value;
+
+@Value
+@Builder
+public class AsyncApiFile {
+
+ JsonNode asyncApiFileNode;
+
+ @Singular("apiServer")
+ transient Map apiServerMap;
+
+ @Singular("apiAsyncApiSR")
+ transient List apiAsyncApiSRList;
+
+ @Singular("apiSchema")
+ transient Map apiSchemaList;
+}
diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSR.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSR.java
new file mode 100644
index 00000000..d4ee6446
--- /dev/null
+++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSR.java
@@ -0,0 +1,17 @@
+package com.sngular.kloadgen.extractor.model;
+
+import java.util.Map;
+
+public record AsyncApiSR(String name, String schemaRegistryUrl,
+ String schemaRegistryVendor) implements AsyncApiAbstract {
+
+ @Override
+ public Object[] getProperties() {
+ return new Object[]{schemaRegistryUrl, schemaRegistryVendor};
+ }
+
+ @Override
+ public Map getPropertiesMap() {
+ return Map.of("url", schemaRegistryUrl, "type", schemaRegistryVendor);
+ }
+}
diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSchema.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSchema.java
new file mode 100644
index 00000000..3537cd33
--- /dev/null
+++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiSchema.java
@@ -0,0 +1,33 @@
+package com.sngular.kloadgen.extractor.model;
+
+import java.util.List;
+
+import com.sngular.kloadgen.model.FieldValueMapping;
+import lombok.Builder;
+import lombok.Value;
+
+@Value
+@Builder
+
+public class AsyncApiSchema implements AsyncApiAbstract {
+
+ String topicName;
+
+ boolean key;
+
+ String keyType;
+
+ String schemaLookupStrategy;
+
+ List model;
+
+ @Override
+ public Object[] getProperties() {
+ return model.toArray();
+ }
+
+ @Override
+ public String toString() {
+ return topicName;
+ }
+}
diff --git a/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiServer.java b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiServer.java
new file mode 100644
index 00000000..a27ec386
--- /dev/null
+++ b/src/main/java/com/sngular/kloadgen/extractor/model/AsyncApiServer.java
@@ -0,0 +1,29 @@
+package com.sngular.kloadgen.extractor.model;
+
+import java.util.Map;
+
+import lombok.Builder;
+import lombok.Value;
+
+@Value
+@Builder
+public class AsyncApiServer implements AsyncApiAbstract {
+
+ String name;
+
+ String url;
+
+ String protocol;
+
+ String description;
+
+ @Override
+ public Object[] getProperties() {
+ return new Object[] {name, url, protocol, description};
+ }
+
+ @Override
+ public Map getPropertiesMap() {
+ return Map.of("name", name, "url", url, "protocol", protocol);
+ }
+}
diff --git a/src/main/java/com/sngular/kloadgen/loadgen/BaseLoadGenerator.java b/src/main/java/com/sngular/kloadgen/loadgen/BaseLoadGenerator.java
index 83851d01..388e3053 100644
--- a/src/main/java/com/sngular/kloadgen/loadgen/BaseLoadGenerator.java
+++ b/src/main/java/com/sngular/kloadgen/loadgen/BaseLoadGenerator.java
@@ -18,5 +18,9 @@ public interface BaseLoadGenerator {
void setUpGenerator(String schema, List fieldExprMappings);
+ default void setUpGenerator(List fieldExprMappings) {
+ this.setUpGenerator(null, fieldExprMappings);
+ }
+
EnrichedRecord nextMessage();
}
diff --git a/src/main/java/com/sngular/kloadgen/loadgen/impl/JsonSRLoadGenerator.java b/src/main/java/com/sngular/kloadgen/loadgen/impl/JsonSRLoadGenerator.java
index 55faf553..5f45062c 100644
--- a/src/main/java/com/sngular/kloadgen/loadgen/impl/JsonSRLoadGenerator.java
+++ b/src/main/java/com/sngular/kloadgen/loadgen/impl/JsonSRLoadGenerator.java
@@ -10,6 +10,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import com.sngular.kloadgen.common.SchemaTypeEnum;
import com.sngular.kloadgen.exception.KLoadGenException;
@@ -56,10 +57,23 @@ public void setUpGenerator(final String schema, final List fi
this.jsonSchemaProcessor.processSchema(SchemaTypeEnum.JSON, null, null, fieldExprMappings);
}
+ @Override
+ public void setUpGenerator(final List fieldExprMappings) {
+
+ this.jsonSchemaProcessor.processSchema(SchemaTypeEnum.JSON, null, null, fieldExprMappings);
+ }
+
public EnrichedRecord nextMessage() {
- return EnrichedRecord.builder().schemaMetadata(
- metadata.getLeft().getSchemaMetadataAdapter()
- ).genericRecord(jsonSchemaProcessor.next()).build();
+ final EnrichedRecord.EnrichedRecordBuilder builder = EnrichedRecord.builder();
+
+ if (Objects.nonNull(metadata)) {
+ builder.schemaMetadata(
+ metadata.getLeft().getSchemaMetadataAdapter()
+ );
+ }
+ builder.genericRecord(jsonSchemaProcessor.next()).build();
+
+ return builder.build();
}
}
diff --git a/src/main/java/com/sngular/kloadgen/model/ConstraintTypeEnum.java b/src/main/java/com/sngular/kloadgen/model/ConstraintTypeEnum.java
index 81f10718..a3abce2a 100644
--- a/src/main/java/com/sngular/kloadgen/model/ConstraintTypeEnum.java
+++ b/src/main/java/com/sngular/kloadgen/model/ConstraintTypeEnum.java
@@ -15,5 +15,5 @@ public enum ConstraintTypeEnum {
REGEX,
FORMAT,
PRECISION,
- SCALE
+ MIN_LENGTH, MAX_LENGTH, SCALE
}
diff --git a/src/main/java/com/sngular/kloadgen/model/FieldValueMapping.java b/src/main/java/com/sngular/kloadgen/model/FieldValueMapping.java
index c7882fae..6950ff1b 100644
--- a/src/main/java/com/sngular/kloadgen/model/FieldValueMapping.java
+++ b/src/main/java/com/sngular/kloadgen/model/FieldValueMapping.java
@@ -19,6 +19,7 @@
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.sngular.kloadgen.extractor.model.AsyncApiAbstract;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
@@ -29,7 +30,7 @@
@ToString
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false)
-public class FieldValueMapping extends AbstractTestElement {
+public class FieldValueMapping extends AbstractTestElement implements AsyncApiAbstract {
public static final String FIELD_CONSTRAINTS = "constraints";
@@ -182,6 +183,10 @@ public final void setConstraints(final Map constrain
this.constraints = constraints;
}
+ public final Object[] getProperties() {
+ return new Object[] {getFieldName(), getFieldType(), getValueLength(), getRequired(), getFieldValuesList()};
+ }
+
public static final class FieldValueMappingBuilder {
private final Map constraints = new EnumMap<>(ConstraintTypeEnum.class);
diff --git a/src/main/java/com/sngular/kloadgen/parsedschema/AbstractParsedSchema.java b/src/main/java/com/sngular/kloadgen/parsedschema/AbstractParsedSchema.java
new file mode 100644
index 00000000..5df54d30
--- /dev/null
+++ b/src/main/java/com/sngular/kloadgen/parsedschema/AbstractParsedSchema.java
@@ -0,0 +1,33 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package com.sngular.kloadgen.parsedschema;
+
+import lombok.Getter;
+
+@Getter
+public abstract class AbstractParsedSchema {
+
+ private final T schema;
+ private final String schemaType;
+ private final String name;
+
+ public AbstractParsedSchema(final String name, final String type, final T schema) {
+ this.name = name;
+ this.schemaType = type;
+ this.schema = schema;
+ }
+
+ public final T schema() {
+ return this.schema;
+ }
+
+ public final String schemaType() {
+ return this.schemaType;
+ }
+
+ public abstract T getRawSchema();
+}
diff --git a/src/main/java/com/sngular/kloadgen/parsedschema/AvroParsedSchema.java b/src/main/java/com/sngular/kloadgen/parsedschema/AvroParsedSchema.java
new file mode 100644
index 00000000..5d5a855b
--- /dev/null
+++ b/src/main/java/com/sngular/kloadgen/parsedschema/AvroParsedSchema.java
@@ -0,0 +1,21 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package com.sngular.kloadgen.parsedschema;
+
+import org.apache.avro.Schema;
+
+public class AvroParsedSchema extends AbstractParsedSchema {
+
+ public AvroParsedSchema(final String name, final Schema schema) {
+ super(name, "AVRO", schema);
+ }
+
+ @Override
+ public final Schema getRawSchema() {
+ return getSchema();
+ }
+}
diff --git a/src/main/java/com/sngular/kloadgen/parsedschema/IParsedSchema.java b/src/main/java/com/sngular/kloadgen/parsedschema/IParsedSchema.java
deleted file mode 100644
index b7d46327..00000000
--- a/src/main/java/com/sngular/kloadgen/parsedschema/IParsedSchema.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.sngular.kloadgen.parsedschema;
-
-public interface IParsedSchema {
-
- String schemaType();
-
- String name();
-
- String canonicalString();
-
- Object rawSchema();
-
-}
diff --git a/src/main/java/com/sngular/kloadgen/parsedschema/JsonParsedSchema.java b/src/main/java/com/sngular/kloadgen/parsedschema/JsonParsedSchema.java
new file mode 100644
index 00000000..e5813c50
--- /dev/null
+++ b/src/main/java/com/sngular/kloadgen/parsedschema/JsonParsedSchema.java
@@ -0,0 +1,19 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package com.sngular.kloadgen.parsedschema;
+
+public class JsonParsedSchema extends AbstractParsedSchema {
+
+ public JsonParsedSchema(final String name, final String schema) {
+ super(name, "JSON", schema);
+ }
+
+ @Override
+ public final String getRawSchema() {
+ return getSchema();
+ }
+}
diff --git a/src/main/java/com/sngular/kloadgen/parsedschema/ParsedSchema.java b/src/main/java/com/sngular/kloadgen/parsedschema/ParsedSchema.java
deleted file mode 100644
index 43aec860..00000000
--- a/src/main/java/com/sngular/kloadgen/parsedschema/ParsedSchema.java
+++ /dev/null
@@ -1,150 +0,0 @@
-package com.sngular.kloadgen.parsedschema;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
-
-import com.sngular.kloadgen.exception.KLoadGenException;
-import com.squareup.wire.schema.internal.parser.ProtoFileElement;
-import io.confluent.kafka.schemaregistry.avro.AvroSchema;
-import io.confluent.kafka.schemaregistry.json.JsonSchema;
-import io.confluent.kafka.schemaregistry.protobuf.ProtobufSchema;
-import org.apache.avro.Schema;
-
-public class ParsedSchema implements IParsedSchema {
-
- private final T schema;
- private final String schemaType;
-
- public ParsedSchema(final String fileContent, final String schemaType) {
- switch (schemaType) {
- case "AVRO" -> {
- this.schema = (T) new Schema.Parser().parse(fileContent);
- }
- case "JSON" -> {
- this.schema = (T) new JsonSchema(fileContent);
- }
- case "PROTOBUF" -> {
- this.schema = (T) new ProtobufSchema(fileContent);
- }
- default -> throw new IllegalArgumentException("schemaType not supported: " + schemaType);
- }
- this.schemaType = schemaType;
- }
-
- public ParsedSchema(final File file, final String schemaType) throws IOException {
- this(new String(Files.readAllBytes(file.toPath())), schemaType);
- }
-
- public ParsedSchema(final T schema, final String type) {
- this.schema = schema;
- this.schemaType = type;
- }
-
- public ParsedSchema(final T schema) {
- this.schema = schema;
- this.schemaType = switch (this.schema.getClass().getSimpleName()) {
- case "Schema", "AvroSchema", "UnionSchema", "RecordSchema" -> "AVRO";
- case "ProtoBuf", "ProtoFileElement" -> "PROTOBUF";
- case "JsonSchema", "ObjectSchema" -> "JSON";
- default -> throw new KLoadGenException(String.format("Need to specify schemaType for %s", this.schema.getClass().getSimpleName()));
- };
- }
-
- public ParsedSchema(final io.confluent.kafka.schemaregistry.ParsedSchema parsedSchema) throws IOException {
- this(parsedSchema.canonicalString(), parsedSchema.schemaType());
- }
-
- public final Object schema() {
- return this.schema;
- }
-
- public final String schemaType() {
- return this.schemaType;
- }
-
- public final String name() {
- return null;
- }
-
- public final String canonicalString() {
- return switch (this.schemaType) {
- case "AVRO" -> stringAvro(this.schema);
- case "JSON" -> stringJson(this.schema);
- case "PROTOBUF" -> stringProto(this.schema);
- default -> this.schema.toString();
- };
- }
-
- private String stringAvro(final T schema) {
- final String result;
- if (schema instanceof AvroSchema) {
- result = ((AvroSchema) this.schema).canonicalString();
- } else {
- result = this.schema.toString();
- }
- return result;
- }
-
- private String stringJson(final T schema) {
- final String result;
- if (schema instanceof JsonSchema) {
- result = ((JsonSchema) this.schema).canonicalString();
- } else {
- result = this.schema.toString();
- }
- return result;
- }
-
- private String stringProto(final T schema) {
- final String result;
- if (schema instanceof ProtobufSchema) {
- result = ((ProtobufSchema) this.schema).canonicalString();
- } else if (schema instanceof ProtoFileElement) {
- result = ((ProtoFileElement) this.schema).toSchema();
- } else {
- result = this.schema.toString();
- }
- return result;
- }
-
- public final Object rawSchema() {
- return switch (this.schemaType) {
- case "AVRO" -> rawAvro(this.schema);
- case "JSON" -> rawJson(this.schema);
- case "PROTOBUF" -> rawProto(this.schema);
- default -> this.schema;
- };
- }
-
- private Object rawAvro(final T schema) {
- final Object result;
- if (schema instanceof AvroSchema) {
- result = ((AvroSchema) this.schema).rawSchema();
- } else {
- result = this.schema;
- }
- return result;
- }
-
- private Object rawJson(final T schema) {
- final Object result;
- if (schema instanceof JsonSchema) {
- result = ((JsonSchema) this.schema).rawSchema();
- } else {
- result = this.schema.toString();
- }
- return result;
- }
-
- private Object rawProto(final T schema) {
- final Object result;
- if (schema instanceof ProtobufSchema) {
- result = ((ProtobufSchema) this.schema).rawSchema();
- } else {
- result = this.schema;
- }
- return result;
- }
-
-}
diff --git a/src/main/java/com/sngular/kloadgen/parsedschema/ProtobufParsedSchema.java b/src/main/java/com/sngular/kloadgen/parsedschema/ProtobufParsedSchema.java
new file mode 100644
index 00000000..bf2fc862
--- /dev/null
+++ b/src/main/java/com/sngular/kloadgen/parsedschema/ProtobufParsedSchema.java
@@ -0,0 +1,21 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package com.sngular.kloadgen.parsedschema;
+
+import com.squareup.wire.schema.internal.parser.ProtoFileElement;
+
+public class ProtobufParsedSchema extends AbstractParsedSchema {
+
+ public ProtobufParsedSchema(final String name, final ProtoFileElement schema) {
+ super(name, "PROTOBUF", schema);
+ }
+
+ @Override
+ public final ProtoFileElement getRawSchema() {
+ return getSchema();
+ }
+}
diff --git a/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java b/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java
index b5f44f6a..cf930146 100644
--- a/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java
+++ b/src/main/java/com/sngular/kloadgen/processor/SchemaProcessor.java
@@ -21,6 +21,7 @@
import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata;
import com.sngular.kloadgen.schemaregistry.adapter.impl.SchemaMetadataAdapter;
import lombok.SneakyThrows;
+import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.RandomUtils;
public class SchemaProcessor {
@@ -165,9 +166,34 @@ private void makeFieldValueMappingRequired(final FieldValueMapping fieldValueMap
}
private ArrayDeque calculateFieldsToProcess() {
+
+ ArrayDeque fieldToProcess;
final ArrayDeque initialFieldExpMappingsQueue = new ArrayDeque<>(fieldExprMappings);
- return initialFieldExpMappingsQueue.stream().filter(fieldValueMapping -> shouldProcessField(fieldValueMapping, initialFieldExpMappingsQueue))
- .collect(Collectors.toCollection(ArrayDeque::new));
+ fieldToProcess = new ArrayDeque<>(ListUtils.select(fieldExprMappings, fieldValueMapping -> shouldProcessField(fieldValueMapping, initialFieldExpMappingsQueue)));
+
+
+ if (fieldToProcess.isEmpty()) {
+ fieldToProcess = new ArrayDeque<>(ListUtils.select(fieldExprMappings, this::shouldProcessFieldIfIsNonRequiered));
+ if (fieldToProcess.isEmpty()) {
+ while (initialFieldExpMappingsQueue.size() > 1) {
+ initialFieldExpMappingsQueue.removeFirst();
+ }
+ fieldToProcess = initialFieldExpMappingsQueue;
+ }
+ }
+
+ return fieldToProcess;
+ }
+
+ private boolean shouldProcessFieldIfIsNonRequiered(final FieldValueMapping fieldValueMapping) {
+
+ boolean shouldProcess = false;
+ if (fieldValueMapping.getFieldValuesList().isEmpty() || fieldValueMapping.getFieldValuesList().contains("null")) {
+ fieldValueMapping.getFieldValuesList().remove("null");
+ } else {
+ shouldProcess = true;
+ }
+ return shouldProcess;
}
private boolean shouldProcessField(final FieldValueMapping fieldValueMapping, final ArrayDeque initialFieldExpMappingsQueue) {
diff --git a/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/AvroObjectCreatorFactory.java b/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/AvroObjectCreatorFactory.java
index 5bb260bc..d631c43a 100644
--- a/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/AvroObjectCreatorFactory.java
+++ b/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/AvroObjectCreatorFactory.java
@@ -14,14 +14,11 @@
import com.sngular.kloadgen.exception.KLoadGenException;
import com.sngular.kloadgen.model.ConstraintTypeEnum;
-import com.sngular.kloadgen.parsedschema.ParsedSchema;
+import com.sngular.kloadgen.parsedschema.AvroParsedSchema;
import com.sngular.kloadgen.processor.model.SchemaProcessorPOJO;
import com.sngular.kloadgen.processor.objectcreatorfactory.ObjectCreatorFactory;
import com.sngular.kloadgen.processor.util.SchemaProcessorUtils;
import com.sngular.kloadgen.randomtool.generator.AvroGeneratorTool;
-import com.sngular.kloadgen.schemaregistry.adapter.impl.AbstractParsedSchemaAdapter;
-import com.sngular.kloadgen.schemaregistry.adapter.impl.ApicurioAbstractParsedSchemaMetadata;
-import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseParsedSchema;
import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata;
import com.sngular.kloadgen.schemaregistry.adapter.impl.SchemaMetadataAdapter;
import com.sngular.kloadgen.serializer.EnrichedRecord;
@@ -44,18 +41,10 @@ public final class AvroObjectCreatorFactory implements ObjectCreatorFactory {
private final Map entity = new HashMap<>();
public AvroObjectCreatorFactory(final Object schema, final BaseSchemaMetadata extends SchemaMetadataAdapter> metadata) {
- if (schema instanceof ParsedSchema) {
- this.schema = (Schema) ((ParsedSchema) schema).rawSchema();
+ if (schema instanceof AvroParsedSchema) {
+ this.schema = ((AvroParsedSchema) schema).getRawSchema();
} else if (schema instanceof Schema) {
this.schema = (Schema) schema;
- } else if (schema instanceof BaseParsedSchema) {
- final BaseParsedSchema schemaParse = (BaseParsedSchema) schema;
- final AbstractParsedSchemaAdapter adapterParse = schemaParse.getParsedSchemaAdapter();
- if (adapterParse instanceof ApicurioAbstractParsedSchemaMetadata) {
- this.schema = (Schema) ((ApicurioAbstractParsedSchemaMetadata) adapterParse).getSchema();
- } else {
- this.schema = adapterParse.getRawSchema();
- }
} else {
throw new KLoadGenException("Unsupported schema type");
}
diff --git a/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/ProtobufObjectCreatorFactory.java b/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/ProtobufObjectCreatorFactory.java
index 9420c220..2559fa3b 100644
--- a/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/ProtobufObjectCreatorFactory.java
+++ b/src/main/java/com/sngular/kloadgen/processor/objectcreatorfactory/impl/ProtobufObjectCreatorFactory.java
@@ -20,13 +20,11 @@
import com.google.protobuf.DynamicMessage.Builder;
import com.google.protobuf.Message;
import com.sngular.kloadgen.exception.KLoadGenException;
-import com.sngular.kloadgen.parsedschema.ParsedSchema;
+import com.sngular.kloadgen.parsedschema.AbstractParsedSchema;
import com.sngular.kloadgen.processor.model.SchemaProcessorPOJO;
import com.sngular.kloadgen.processor.objectcreatorfactory.ObjectCreatorFactory;
import com.sngular.kloadgen.processor.util.SchemaProcessorUtils;
import com.sngular.kloadgen.randomtool.generator.ProtoBufGeneratorTool;
-import com.sngular.kloadgen.schemaregistry.adapter.impl.AbstractParsedSchemaAdapter;
-import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseParsedSchema;
import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata;
import com.sngular.kloadgen.schemaregistry.adapter.impl.SchemaMetadataAdapter;
import com.sngular.kloadgen.serializer.EnrichedRecord;
@@ -44,15 +42,10 @@ public class ProtobufObjectCreatorFactory implements ObjectCreatorFactory {
private final Map entity = new HashMap<>();
public ProtobufObjectCreatorFactory(final Object schema, final BaseSchemaMetadata extends SchemaMetadataAdapter> metadata) throws DescriptorValidationException, IOException {
- if (schema instanceof ParsedSchema) {
- this.schema = SchemaProcessorUtils.buildProtoDescriptor((ProtoFileElement) ((ParsedSchema) schema).rawSchema(), metadata);
+ if (schema instanceof AbstractParsedSchema) {
+ this.schema = SchemaProcessorUtils.buildProtoDescriptor((ProtoFileElement) ((AbstractParsedSchema) schema).getRawSchema(), metadata);
} else if (schema instanceof ProtoFileElement) {
this.schema = SchemaProcessorUtils.buildProtoDescriptor((ProtoFileElement) schema, metadata);
- } else if (schema instanceof BaseParsedSchema) {
- final BaseParsedSchema schemaParse = (BaseParsedSchema) schema;
- final AbstractParsedSchemaAdapter adapterParse = schemaParse.getParsedSchemaAdapter();
- final Object schemaParsed = adapterParse.getRawSchema();
- this.schema = SchemaProcessorUtils.buildProtoDescriptor((ProtoFileElement) schemaParsed, metadata);
} else {
throw new KLoadGenException("Unsupported schema type");
}
diff --git a/src/main/java/com/sngular/kloadgen/processor/util/SchemaProcessorUtils.java b/src/main/java/com/sngular/kloadgen/processor/util/SchemaProcessorUtils.java
index 8f035c90..468108cb 100644
--- a/src/main/java/com/sngular/kloadgen/processor/util/SchemaProcessorUtils.java
+++ b/src/main/java/com/sngular/kloadgen/processor/util/SchemaProcessorUtils.java
@@ -26,7 +26,6 @@
import com.google.protobuf.Descriptors;
import com.google.protobuf.Descriptors.DescriptorValidationException;
import com.sngular.kloadgen.model.FieldValueMapping;
-import com.sngular.kloadgen.schemaregistry.adapter.impl.AbstractParsedSchemaAdapter;
import com.sngular.kloadgen.schemaregistry.adapter.impl.BaseSchemaMetadata;
import com.sngular.kloadgen.schemaregistry.adapter.impl.SchemaMetadataAdapter;
import com.sngular.kloadgen.util.JMeterHelper;
@@ -187,9 +186,10 @@ private static void processImport(final BaseSchemaMetadata extends SchemaMetad
schemaBuilder.addSchema(importedSchema);
}
} else {
- final AbstractParsedSchemaAdapter protoFileElement = JMeterHelper.getParsedSchema(getSubjectName(importedClass, metadata),
- JMeterContextService.getContext().getProperties()).getParsedSchemaAdapter();
- final var importedProtobufSchema = new ProtobufSchema(protoFileElement.getRawSchema(), metadata.getSchemaMetadataAdapter().getReferences(), new HashMap<>());
+ final var protoFileElement = JMeterHelper.getParsedSchema(getSubjectName(importedClass, metadata),
+ JMeterContextService.getContext().getProperties());
+ final var importedProtobufSchema = new ProtobufSchema(
+ (ProtoFileElement) protoFileElement.getSchema(), metadata.getSchemaMetadataAdapter().getReferences(), new HashMap<>());
if (!ProtobufHelper.NOT_ACCEPTED_IMPORTS.contains(importedClass)) {
schemaBuilder.addDependency(importedProtobufSchema.toDescriptor().getFullName());
schemaBuilder.addSchema(convertDynamicSchema(importedProtobufSchema, metadata));
diff --git a/src/main/java/com/sngular/kloadgen/property/editor/FileSubjectPropertyEditor.java b/src/main/java/com/sngular/kloadgen/property/editor/FileSubjectPropertyEditor.java
index 33413c8c..7cc17314 100644
--- a/src/main/java/com/sngular/kloadgen/property/editor/FileSubjectPropertyEditor.java
+++ b/src/main/java/com/sngular/kloadgen/property/editor/FileSubjectPropertyEditor.java
@@ -30,9 +30,8 @@
import com.sngular.kloadgen.common.SchemaTypeEnum;
import com.sngular.kloadgen.extractor.SchemaExtractor;
import com.sngular.kloadgen.extractor.extractors.ExtractorFactory;
-import com.sngular.kloadgen.extractor.extractors.ExtractorRegistry;
import com.sngular.kloadgen.model.FieldValueMapping;
-import com.sngular.kloadgen.parsedschema.ParsedSchema;
+import com.sngular.kloadgen.parsedschema.AbstractParsedSchema;
import com.sngular.kloadgen.util.PropsKeysHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.avro.AvroRuntimeException;
@@ -94,9 +93,9 @@ public final void actionFileChooser(final ActionEvent event) {
final File schemaFile = Objects.requireNonNull(fileChooser.getSelectedFile());
try {
final String schemaType = schemaTypeComboBox.getSelectedItem().toString();
- final ExtractorRegistry extractor = ExtractorFactory.getExtractor(schemaType);
+ final var extractor = ExtractorFactory.getExtractor(schemaType);
final String fileContent = SchemaExtractor.readSchemaFile(schemaFile.getPath());
- final ParsedSchema parserSchema = (ParsedSchema) extractor.processSchema(fileContent);
+ final var parserSchema = extractor.processSchema(fileContent);
final List schemaFieldList = extractor.processSchema(parserSchema, SchemaRegistryEnum.CONFLUENT);
buildTable(schemaFieldList, fileContent, schemaType);
} catch (final IOException e) {
@@ -107,7 +106,7 @@ public final void actionFileChooser(final ActionEvent event) {
}
}
- public final List getAttributeList(final ParsedSchema selectedSchema) {
+ public final List getAttributeList(final AbstractParsedSchema selectedSchema) {
final List result = new ArrayList<>();
if (Objects.nonNull(selectedSchema)) {
result.addAll(SchemaExtractor.flatPropertiesList(selectedSchema));
diff --git a/src/main/java/com/sngular/kloadgen/property/editor/SerDesPackageValue.java b/src/main/java/com/sngular/kloadgen/property/editor/SerDesPackageValue.java
index cf55f1c9..760ae41a 100644
--- a/src/main/java/com/sngular/kloadgen/property/editor/SerDesPackageValue.java
+++ b/src/main/java/com/sngular/kloadgen/property/editor/SerDesPackageValue.java
@@ -1,3 +1,9 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
package com.sngular.kloadgen.property.editor;
public class SerDesPackageValue {
diff --git a/src/main/java/com/sngular/kloadgen/randomtool/generator/ProtoBufGeneratorTool.java b/src/main/java/com/sngular/kloadgen/randomtool/generator/ProtoBufGeneratorTool.java
index f3fe5164..4def6ee0 100644
--- a/src/main/java/com/sngular/kloadgen/randomtool/generator/ProtoBufGeneratorTool.java
+++ b/src/main/java/com/sngular/kloadgen/randomtool/generator/ProtoBufGeneratorTool.java
@@ -1,3 +1,9 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
package com.sngular.kloadgen.randomtool.generator;
import java.util.ArrayList;
diff --git a/src/main/java/com/sngular/kloadgen/randomtool/random/RandomObject.java b/src/main/java/com/sngular/kloadgen/randomtool/random/RandomObject.java
index 0a959b62..aa5dfd5d 100644
--- a/src/main/java/com/sngular/kloadgen/randomtool/random/RandomObject.java
+++ b/src/main/java/com/sngular/kloadgen/randomtool/random/RandomObject.java
@@ -85,7 +85,8 @@ public Object generateRandom(
break;
case ValidTypeConstants.BYTES:
try {
- value = getIntegerValueOrRandom(valueLength, Collections.emptyList(), Collections.emptyMap()).byteValueExact();
+ value = getIntegerValueOrRandom(valueLength, Collections.emptyList(), Collections.emptyMap())
+ .byteValueExact();
} catch (final ArithmeticException exception) {
value = Byte.MAX_VALUE;
}
@@ -149,7 +150,8 @@ public Object generateRandom(
return value;
}
- private BigInteger getIntegerValueOrRandom(final Integer valueLength, final List fieldValueList, final Map constraints) {
+ private BigInteger getIntegerValueOrRandom(final Integer valueLength, final List fieldValueList,
+ final Map constraints) {
final BigInteger value;
if (!fieldValueList.isEmpty()) {
@@ -176,7 +178,8 @@ private BigInteger getIntegerValueOrRandom(final Integer valueLength, final List
return value;
}
- private BigDecimal getDecimalValueOrRandom(final Integer valueLength, final List fieldValueList, final Map constraints) {
+ private BigDecimal getDecimalValueOrRandom(final Integer valueLength, final List fieldValueList,
+ final Map constraints) {
final BigDecimal value;
if (!fieldValueList.isEmpty()) {
@@ -421,8 +424,10 @@ private static LocalTime getTimeMicrosValueOrRandom(final List fieldValu
private static LocalDateTime getRandomLocalDateTime(final List fieldValueList) {
final LocalDateTime value;
- final long minDay = LocalDateTime.of(1900, 1, 1, 0, 0).toEpochSecond(ZoneOffset.UTC);
- final long maxDay = LocalDateTime.of(2100, 1, 1, 0, 0).toEpochSecond(ZoneOffset.UTC);
+ final long minDay = LocalDateTime.of(1900, 1, 1, 0, 0)
+ .toEpochSecond(ZoneOffset.UTC);
+ final long maxDay = LocalDateTime.of(2100, 1, 1, 0, 0)
+ .toEpochSecond(ZoneOffset.UTC);
final long randomSeconds = minDay + RandomUtils.nextLong(0, maxDay - minDay);
if (fieldValueList.isEmpty()) {
diff --git a/src/main/java/com/sngular/kloadgen/randomtool/util/ValueUtils.java b/src/main/java/com/sngular/kloadgen/randomtool/util/ValueUtils.java
index 285d9442..c06c8ac2 100644
--- a/src/main/java/com/sngular/kloadgen/randomtool/util/ValueUtils.java
+++ b/src/main/java/com/sngular/kloadgen/randomtool/util/ValueUtils.java
@@ -16,6 +16,7 @@
import java.util.UUID;
import org.apache.avro.Schema;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.jmeter.threads.JMeterContextService;
public class ValueUtils {
@@ -25,11 +26,13 @@ private ValueUtils() {
}
public static List replaceValuesContext(final List fieldValuesList) {
- final List parameterList = new ArrayList<>(fieldValuesList);
-
- parameterList.replaceAll(fieldValue ->
- fieldValue.matches("\\$\\{\\w*}")
- ? JMeterContextService.getContext().getVariables().get(fieldValue.substring(2, fieldValue.length() - 1)) : fieldValue);
+ final List parameterList = new ArrayList<>();
+ if (CollectionUtils.isNotEmpty(fieldValuesList)) {
+ parameterList.addAll(fieldValuesList);
+ parameterList.replaceAll(fieldValue ->
+ fieldValue.matches("\\$\\{\\w*}")
+ ? JMeterContextService.getContext().getVariables().get(fieldValue.substring(2, fieldValue.length() - 1)) : fieldValue);
+ }
return parameterList;
}
diff --git a/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java
new file mode 100644
index 00000000..2705b831
--- /dev/null
+++ b/src/main/java/com/sngular/kloadgen/sampler/AsyncApiSampler.java
@@ -0,0 +1,210 @@
+package com.sngular.kloadgen.sampler;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ExecutionException;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.sngular.kloadgen.exception.KLoadGenException;
+import com.sngular.kloadgen.extractor.ApiExtractor;
+import com.sngular.kloadgen.extractor.asyncapi.AsyncApiExtractorImpl;
+import com.sngular.kloadgen.extractor.model.AsyncApiFile;
+import com.sngular.kloadgen.loadgen.BaseLoadGenerator;
+import com.sngular.kloadgen.loadgen.impl.JsonSRLoadGenerator;
+import com.sngular.kloadgen.model.FieldValueMapping;
+import com.sngular.kloadgen.model.PropertyMapping;
+import com.sngular.kloadgen.serializer.EnrichedRecord;
+import com.sngular.kloadgen.serializer.GenericJsonRecordSerializer;
+import com.sngular.kloadgen.util.PropsKeysHelper;
+import org.apache.jmeter.config.ConfigTestElement;
+import org.apache.jmeter.gui.GUIMenuSortOrder;
+import org.apache.jmeter.samplers.AbstractSampler;
+import org.apache.jmeter.samplers.Entry;
+import org.apache.jmeter.samplers.SampleResult;
+import org.apache.jmeter.testelement.property.CollectionProperty;
+import org.apache.jmeter.testelement.property.TestElementProperty;
+import org.apache.kafka.clients.producer.KafkaProducer;
+import org.apache.kafka.clients.producer.ProducerConfig;
+import org.apache.kafka.clients.producer.ProducerRecord;
+import org.apache.kafka.clients.producer.RecordMetadata;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@GUIMenuSortOrder(Integer.MIN_VALUE)
+public class AsyncApiSampler extends AbstractSampler implements Serializable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AsyncApiSampler.class);
+
+ private static final String TEMPLATE = "Topic: %s, partition: %s, offset: %s";
+
+ private final transient ApiExtractor apiExtractor;
+
+ private final transient BaseLoadGenerator generator;
+
+ private final transient ObjectMapper mapper = new ObjectMapper();
+
+ private JsonNode asyncApiFileNode;
+
+ public AsyncApiSampler() {
+ apiExtractor = new AsyncApiExtractorImpl();
+ generator = new JsonSRLoadGenerator();
+ }
+
+ @Override
+ public final boolean applies(final ConfigTestElement configElement) {
+ return super.applies(configElement);
+ }
+
+ @Override
+ public final SampleResult sample(final Entry entry) {
+
+ final var sampleResult = new SampleResult();
+ sampleResult.setThreadName("AsyncApi Sampler");
+ sampleResult.sampleStart();
+ try (final KafkaProducer