class PropertiesConverter implements PropertyConverter {

    @Override
    public CompletionStage<PropertyContext<?>> convert(final CompletionStage<PropertyContext<?>> cs) {
        return cs.thenCompose(context -> {
            final SimplePropertyDefinition property = context.getProperty();
            if ("object".equalsIgnoreCase(property.getType())) {
                final Map<String, Object> childDefaults = new HashMap<>();
                defaults.put(property.getName(), childDefaults);
                final PropertiesConverter propertiesConverter =
                        new PropertiesConverter(jsonb, childDefaults, properties);

                return CompletableFuture
                        .allOf(context
                                .findDirectChild(properties)
                                .map(it -> new PropertyContext<>(it, context.getRootContext(),
                                        context.getConfiguration()))
                                .map(CompletionStages::toStage)
                                .map(propertiesConverter::convert)
                                .toArray(CompletableFuture[]::new))
                        .thenApply(done -> context);
            }

            ofNullable(property.getMetadata().getOrDefault("ui::defaultvalue::value", property.getDefaultValue()))
                    .ifPresent(value -> {
                        if ("number".equalsIgnoreCase(property.getType())) {
                            defaults.put(property.getName(), Double.parseDouble(value));
                        } else if ("boolean".equalsIgnoreCase(property.getType())) {
                            defaults.put(property.getName(), Boolean.parseBoolean(value));
                        } else if ("array".equalsIgnoreCase(property.getType())) {
                            defaults.put(property.getName(), jsonb.fromJson(value, Object[].class));
                        } else if ("object".equalsIgnoreCase(property.getType())) {
                            defaults.put(property.getName(), jsonb.fromJson(value, Map.class));
                        } else {
                            if ("string".equalsIgnoreCase(property.getType()) && property
                                    .getMetadata()
                                    .keySet()
                                    .stream()
                                    .anyMatch(k -> k.equalsIgnoreCase("action::suggestions")
                                            || k.equalsIgnoreCase("action::dynamic_values"))) {
                                defaults.putIfAbsent("$" + property.getName() + "_name", value);
                            }
                            defaults.put(property.getName(), value);
                        }
                    });
            return CompletableFuture.completedFuture(context);
        });
    }

}