diff --git a/step-api/step-api-json-schema/src/main/java/step/handlers/javahandler/jsonschema/JsonInputConverter.java b/step-api/step-api-json-schema/src/main/java/step/handlers/javahandler/jsonschema/JsonInputConverter.java index 7983c75..ae7c1a1 100644 --- a/step-api/step-api-json-schema/src/main/java/step/handlers/javahandler/jsonschema/JsonInputConverter.java +++ b/step-api/step-api-json-schema/src/main/java/step/handlers/javahandler/jsonschema/JsonInputConverter.java @@ -27,27 +27,14 @@ import java.math.BigInteger; import java.util.Collection; -import static step.handlers.javahandler.JsonInputConverter.resolveGenericTypeForCollection; +import static step.handlers.javahandler.JsonInputConverter.resolveGenericTypeForArrayAndCollection; public class JsonInputConverter { public static final String ARRAY_VALUE_SEPARATOR = ";"; public static void addValueToJsonBuilder(String value, JsonObjectBuilder builder, Type type, String jsonName) throws IllegalArgumentException { - Class clazz; - - try { - if (type instanceof Class) { - clazz = (Class) type; - } else if (type instanceof ParameterizedType) { - // we expect the parameterized collection here - clazz = (Class) ((ParameterizedType) type).getRawType(); - } else { - throw new IllegalArgumentException("Unsupported type " + type + " found for field " + jsonName); - } - } catch (Exception ex) { - throw new IllegalArgumentException("Unsupported type " + type + " found for field " + jsonName); - } + Class clazz = resolveClass(type, jsonName); if(String.class.isAssignableFrom(clazz)){ builder.add(jsonName, value); @@ -66,15 +53,7 @@ public static void addValueToJsonBuilder(String value, JsonObjectBuilder builder } else if(clazz.isArray() || Collection.class.isAssignableFrom(clazz)){ JsonArrayBuilder arrayBuilder = Json.createArrayBuilder(); - Class arrayValueType; - if (clazz.isArray()) { - arrayValueType = clazz.getComponentType(); - } else if (Collection.class.isAssignableFrom(clazz)) { - // we need to check the generic parameter type for collection - arrayValueType = resolveGenericTypeForCollection(type, jsonName); - } else { - throw new IllegalArgumentException("Unsupported type found for array field " + jsonName + ": " + type); - } + Class arrayValueType = resolveGenericTypeForArrayAndCollection(clazz, type, jsonName); for (String arrayValue : value.split(ARRAY_VALUE_SEPARATOR)) { if(String.class.isAssignableFrom(arrayValueType)){ @@ -107,6 +86,23 @@ public static void addValueToJsonBuilder(String value, JsonObjectBuilder builder } } + public static Class resolveClass(Type type, String jsonName) { + Class clazz; + try { + if (type instanceof Class) { + clazz = (Class) type; + } else if (type instanceof ParameterizedType) { + // we expect the parameterized collection here + clazz = (Class) ((ParameterizedType) type).getRawType(); + } else { + throw new IllegalArgumentException("Unsupported type " + type + " found for field " + jsonName); + } + } catch (Exception ex) { + throw new IllegalArgumentException("Unsupported type " + type + " found for field " + jsonName); + } + return clazz; + } + public static String resolveJsonPropertyType(Class type) { if (String.class.isAssignableFrom(type)) { return "string"; diff --git a/step-api/step-api-json-schema/src/main/java/step/handlers/javahandler/jsonschema/KeywordJsonSchemaCreator.java b/step-api/step-api-json-schema/src/main/java/step/handlers/javahandler/jsonschema/KeywordJsonSchemaCreator.java index 8eb3f09..6947f37 100644 --- a/step-api/step-api-json-schema/src/main/java/step/handlers/javahandler/jsonschema/KeywordJsonSchemaCreator.java +++ b/step-api/step-api-json-schema/src/main/java/step/handlers/javahandler/jsonschema/KeywordJsonSchemaCreator.java @@ -30,8 +30,11 @@ import java.io.StringReader; import java.lang.reflect.Method; import java.lang.reflect.Parameter; +import java.lang.reflect.Type; import java.util.*; +import static step.handlers.javahandler.JsonInputConverter.resolveGenericTypeForArrayAndCollection; + public class KeywordJsonSchemaCreator { private final JsonProvider jsonProvider = JsonProvider.provider(); @@ -97,6 +100,15 @@ private JsonObject readJsonSchemaFromInputAnnotations(Method method) throws Json String propertyType = JsonInputConverter.resolveJsonPropertyType(type); propertyParamsBuilder.add("type", propertyType); + if (propertyType.equals("array")) { + //add items type + Type parameterizedType = p.getParameterizedType(); + Class aClass = resolveGenericTypeForArrayAndCollection(JsonInputConverter.resolveClass(parameterizedType, parameterName), parameterizedType, parameterName); + String arrayElementType = JsonInputConverter.resolveJsonPropertyType(aClass); + JsonObject arrayType = jsonProvider.createObjectBuilder().add("type", arrayElementType).build(); + propertyParamsBuilder.add("items", arrayType); + } + if (inputAnnotation.defaultValue() != null && !inputAnnotation.defaultValue().isEmpty()) { try { JsonSchemaCreator.addDefaultValue(inputAnnotation.defaultValue(), propertyParamsBuilder, p.getParameterizedType(), parameterName); diff --git a/step-api/step-api-json-schema/src/test/java/step/handlers/javahandler/jsonschema/KeywordJsonSchemaCreatorTest.java b/step-api/step-api-json-schema/src/test/java/step/handlers/javahandler/jsonschema/KeywordJsonSchemaCreatorTest.java index f11a341..b28fe9e 100644 --- a/step-api/step-api-json-schema/src/test/java/step/handlers/javahandler/jsonschema/KeywordJsonSchemaCreatorTest.java +++ b/step-api/step-api-json-schema/src/test/java/step/handlers/javahandler/jsonschema/KeywordJsonSchemaCreatorTest.java @@ -152,7 +152,8 @@ public void MyKeywordWithInputNestedFieldAnnotation(@Input(name = "stringField", @Keyword public void MyKeywordWithInputArrays(@Input(name = "stringArray", defaultValue = "a;b;c", required = true) String[] stringArray, @Input(name = "integerArray", defaultValue = "1;2;3") Integer[] integerArray, - @Input(name = "stringList", defaultValue = "c;d;e") List stringList) { + @Input(name = "stringList", defaultValue = "c;d;e") List stringList, + @Input(name = "booleanList", defaultValue = "true;false;true") ArrayList booleanList) { output.add("test", "test"); } diff --git a/step-api/step-api-json-schema/src/test/resources/step/handlers/javahandler/jsonschema/expected-json-schema-3.json b/step-api/step-api-json-schema/src/test/resources/step/handlers/javahandler/jsonschema/expected-json-schema-3.json index d2766f4..d744686 100644 --- a/step-api/step-api-json-schema/src/test/resources/step/handlers/javahandler/jsonschema/expected-json-schema-3.json +++ b/step-api/step-api-json-schema/src/test/resources/step/handlers/javahandler/jsonschema/expected-json-schema-3.json @@ -3,15 +3,31 @@ "properties": { "stringArray": { "type": "array", + "items": { + "type": "string" + }, "default": ["a", "b", "c"] }, "integerArray": { "type": "array", + "items": { + "type": "number" + }, "default": [1, 2, 3] }, "stringList": { "type": "array", + "items": { + "type": "string" + }, "default": ["c", "d", "e"] + }, + "booleanList": { + "type": "array", + "items": { + "type": "boolean" + }, + "default": [true, false, true] } }, "required": [ diff --git a/step-api/step-api-keyword/src/main/java/step/handlers/javahandler/JsonInputConverter.java b/step-api/step-api-keyword/src/main/java/step/handlers/javahandler/JsonInputConverter.java index 0432662..953649b 100644 --- a/step-api/step-api-keyword/src/main/java/step/handlers/javahandler/JsonInputConverter.java +++ b/step-api/step-api-keyword/src/main/java/step/handlers/javahandler/JsonInputConverter.java @@ -59,15 +59,7 @@ public static Object getValueFromJsonInput(JsonObject input, String name, String } else if (valueType.isArray() || Collection.class.isAssignableFrom(valueType)) { JsonArray jsonArray = (validInputValue) ? input.getJsonArray(name) : convertStringToJsonArrayBuilder(name, defaultValue, valueType, type).build(); - Class arrayValueType; - if (valueType.isArray()) { - arrayValueType = valueType.getComponentType(); - } else if (Collection.class.isAssignableFrom(valueType)) { - // we need to check the generic parameter type for collection - arrayValueType = resolveGenericTypeForCollection(type, name); - } else { - throw new IllegalArgumentException("Unsupported type found for array input " + name + ": " + type); - } + Class arrayValueType = resolveGenericTypeForArrayAndCollection(valueType, type, name);; Object[] arrayValue = null; if (String.class.isAssignableFrom(arrayValueType)) { arrayValue = new String[jsonArray.size()]; @@ -106,7 +98,11 @@ public static Object getValueFromJsonInput(JsonObject input, String name, String } } if (Collection.class.isAssignableFrom(valueType)) { - value = valueType.getConstructor().newInstance(); + if (valueType.isInterface()) { + value = new ArrayList<>(); + } else { + value = valueType.getConstructor().newInstance(); + } ((Collection) value).addAll(Arrays.asList(arrayValue)); } else { value = arrayValue; @@ -176,15 +172,7 @@ private static Optional getSimpleValueFrom(JsonObject input, String name private static JsonArrayBuilder convertStringToJsonArrayBuilder(String jsonName, String value, Class clazz, Type type) { JsonArrayBuilder arrayBuilder = Json.createArrayBuilder(); - Class arrayValueType; - if (clazz.isArray()) { - arrayValueType = clazz.getComponentType(); - } else if (Collection.class.isAssignableFrom(clazz)) { - // we need to check the generic parameter type for collection - arrayValueType = resolveGenericTypeForCollection(type, jsonName); - } else { - throw new IllegalArgumentException("Unsupported type found for array field " + jsonName + ": " + type); - } + Class arrayValueType = resolveGenericTypeForArrayAndCollection(clazz, type, jsonName);; for (String arrayValue : value.split(ARRAY_VALUE_SEPARATOR)) { if(String.class.isAssignableFrom(arrayValueType)){ @@ -208,6 +196,19 @@ private static JsonArrayBuilder convertStringToJsonArrayBuilder(String jsonName, return arrayBuilder; } + public static Class resolveGenericTypeForArrayAndCollection(Class clazz, Type type, String jsonName) { + Class arrayValueType; + if (clazz.isArray()) { + arrayValueType = clazz.getComponentType(); + } else if (Collection.class.isAssignableFrom(clazz)) { + // we need to check the generic parameter type for collection + arrayValueType = resolveGenericTypeForCollection(type, jsonName); + } else { + throw new IllegalArgumentException("Unsupported type found for array field " + jsonName + ": " + type); + } + return arrayValueType; + } + public static Class resolveGenericTypeForCollection(Type type, String jsonName) { Class arrayValueType; if (!(type instanceof ParameterizedType)) { diff --git a/step-api/step-api-keyword/src/test/java/step/handlers/javahandler/MyKeywordWithInputFields.java b/step-api/step-api-keyword/src/test/java/step/handlers/javahandler/MyKeywordWithInputFields.java index 8341108..b460a46 100644 --- a/step-api/step-api-keyword/src/test/java/step/handlers/javahandler/MyKeywordWithInputFields.java +++ b/step-api/step-api-keyword/src/test/java/step/handlers/javahandler/MyKeywordWithInputFields.java @@ -50,7 +50,8 @@ public void MyKeywordWithInputNested(@Input(name = "stringField", defaultValue = @Keyword public void MyKeywordWithInputArrays(@Input(name = "stringArray", defaultValue = "a;b;c", required = true) String[] stringArray, @Input(name = "integerArray", defaultValue = "1;2;3") Integer[] integerArray, - @Input(name = "stringList", defaultValue = "1;2;3") ArrayList stringList) { + @Input(name = "stringList", defaultValue = "1;2;3") ArrayList stringList, + @Input(name = "booleanList", defaultValue = "true;false;true") ArrayList booleanList) { // fill output to check execution result in tests if (stringArray != null) { output.add("stringArrayOut", Arrays.stream(stringArray).reduce((s, s2) -> s + "+" + s2).orElse("")); @@ -63,6 +64,10 @@ public void MyKeywordWithInputNested(@Input(name = "stringField", defaultValue = if (stringList != null) { output.add("stringListOut", stringList.stream().reduce((s, s2) -> s + "+" + s2).orElse("")); } + + if (booleanList != null) { + output.add("booleanListOut", booleanList.stream().map(Object::toString).reduce((s, s2) -> s + "+" + s2).orElse("")); + } } @Keyword