spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/uber/UberUtils.java
private static void recurseBeanCreationParams(List<UberField> uberFields, Class<?> beanType,
                                                  ActionDescriptor annotatedParameters,
                                                  ActionInputParameter annotatedParameter, Object currentCallValue,
                                                  String parentParamName, Set<String> knownFields) {
        // TODO collection, map and object node creation are only describable by an annotation, not via type reflection
        if (ObjectNode.class.isAssignableFrom(beanType) || Map.class.isAssignableFrom(beanType)
                || Collection.class.isAssignableFrom(beanType) || beanType.isArray()) {
            return; // use @Input(include) to list parameter names, at least? Or mix with hdiv's form builder?
        }
        try {
            Constructor[] constructors = beanType.getConstructors();
            // find default ctor
            Constructor constructor = PropertyUtils.findDefaultCtor(constructors);
            // find ctor with JsonCreator ann
            if (constructor == null) {
                constructor = PropertyUtils.findJsonCreator(constructors, JsonCreator.class);
            }
            Assert.notNull(constructor, "no default constructor or JsonCreator found for type " + beanType
                    .getName());
            int parameterCount = constructor.getParameterTypes().length;

            if (parameterCount > 0) {
                Annotation[][] annotationsOnParameters = constructor.getParameterAnnotations();

                Class[] parameters = constructor.getParameterTypes();
                int paramIndex = 0;
                for (Annotation[] annotationsOnParameter : annotationsOnParameters) {
                    for (Annotation annotation : annotationsOnParameter) {
                        if (JsonProperty.class == annotation.annotationType()) {
                            JsonProperty jsonProperty = (JsonProperty) annotation;

                            // TODO use required attribute of JsonProperty for required fields
                            String paramName = jsonProperty.value();
                            Class parameterType = parameters[paramIndex];
                            Object propertyValue = PropertyUtils.getPropertyOrFieldValue(currentCallValue,
                                    paramName);
                            MethodParameter methodParameter = new MethodParameter(constructor, paramIndex);

                            addUberFieldsForMethodParameter(uberFields, methodParameter, annotatedParameter,
                                    annotatedParameters,
                                    parentParamName, paramName, parameterType, propertyValue,
                                    knownFields);
                            paramIndex++; // increase for each @JsonProperty
                        }
                    }
                }
                Assert.isTrue(parameters.length == paramIndex,
                        "not all constructor arguments of @JsonCreator " + constructor.getName() +
                                " are annotated with @JsonProperty");
            }

            Set<String> knownConstructorFields = new HashSet<String>(uberFields.size());
            for (UberField sirenField : uberFields) {
                knownConstructorFields.add(sirenField.getName());
            }

            // TODO support Option provider by other method args?
            Map<String, PropertyDescriptor> propertyDescriptors = PropertyUtils.getPropertyDescriptors(beanType);

            // add input field for every setter
            for (PropertyDescriptor propertyDescriptor : propertyDescriptors.values()) {
                final Method writeMethod = propertyDescriptor.getWriteMethod();
                String propertyName = propertyDescriptor.getName();

                if (writeMethod == null || knownFields.contains(parentParamName + propertyName)) {
                    continue;
                }
                final Class<?> propertyType = propertyDescriptor.getPropertyType();

                Object propertyValue = PropertyUtils.getPropertyOrFieldValue(currentCallValue, propertyName);
                MethodParameter methodParameter = new MethodParameter(propertyDescriptor.getWriteMethod(), 0);

                addUberFieldsForMethodParameter(uberFields, methodParameter, annotatedParameter,
                        annotatedParameters,
                        parentParamName, propertyName, propertyType, propertyValue, knownConstructorFields);
            }
        } catch (Exception e) {
            throw new RuntimeException("Failed to write input fields for constructor", e);
        }
    }
private static void recurseBeanCreationParams(List<UberField> uberFields, Class<?> beanType,
                                                  ActionDescriptor annotatedParameters,
                                                  ActionInputParameter annotatedParameter, Object currentCallValue,
                                                  String parentParamName, Set<String> knownFields) {
        // TODO collection, map and object node creation are only describable by an annotation, not via type reflection
        if (ObjectNode.class.isAssignableFrom(beanType) || Map.class.isAssignableFrom(beanType)
                || Collection.class.isAssignableFrom(beanType) || beanType.isArray()) {
            return; // use @Input(include) to list parameter names, at least? Or mix with hdiv's form builder?
        }
        try {
            Constructor[] constructors = beanType.getConstructors();
            // find default ctor
            Constructor constructor = PropertyUtils.findDefaultCtor(constructors);
            // find ctor with JsonCreator ann
            if (constructor == null) {
                constructor = PropertyUtils.findJsonCreator(constructors, JsonCreator.class);
            }
            Assert.notNull(constructor, "no default constructor or JsonCreator found for type " + beanType
                    .getName());
            int parameterCount = constructor.getParameterTypes().length;

            if (parameterCount > 0) {
                Annotation[][] annotationsOnParameters = constructor.getParameterAnnotations();

                Class[] parameters = constructor.getParameterTypes();
                int paramIndex = 0;
                for (Annotation[] annotationsOnParameter : annotationsOnParameters) {
                    for (Annotation annotation : annotationsOnParameter) {
                        if (JsonProperty.class == annotation.annotationType()) {
                            JsonProperty jsonProperty = (JsonProperty) annotation;

                            // TODO use required attribute of JsonProperty for required fields
                            String paramName = jsonProperty.value();
                            Class parameterType = parameters[paramIndex];
                            Object propertyValue = PropertyUtils.getPropertyOrFieldValue(currentCallValue,
                                    paramName);
                            MethodParameter methodParameter = new MethodParameter(constructor, paramIndex);

                            addUberFieldsForMethodParameter(uberFields, methodParameter, annotatedParameter,
                                    annotatedParameters,
                                    parentParamName, paramName, parameterType, propertyValue,
                                    knownFields);
                            paramIndex++; // increase for each @JsonProperty
                        }
                    }
                }
                Assert.isTrue(parameters.length == paramIndex,
                        "not all constructor arguments of @JsonCreator " + constructor.getName() +
                                " are annotated with @JsonProperty");
            }

            Set<String> knownConstructorFields = new HashSet<String>(uberFields.size());
            for (UberField sirenField : uberFields) {
                knownConstructorFields.add(sirenField.getName());
            }

            // TODO support Option provider by other method args?
            Map<String, PropertyDescriptor> propertyDescriptors = PropertyUtils.getPropertyDescriptors(beanType);

            // add input field for every setter
            for (PropertyDescriptor propertyDescriptor : propertyDescriptors.values()) {
                final Method writeMethod = propertyDescriptor.getWriteMethod();
                String propertyName = propertyDescriptor.getName();

                if (writeMethod == null || knownFields.contains(parentParamName + propertyName)) {
                    continue;
                }
                final Class<?> propertyType = propertyDescriptor.getPropertyType();

                Object propertyValue = PropertyUtils.getPropertyOrFieldValue(currentCallValue, propertyName);
                MethodParameter methodParameter = new MethodParameter(propertyDescriptor.getWriteMethod(), 0);

                addUberFieldsForMethodParameter(uberFields, methodParameter, annotatedParameter,
                        annotatedParameters,
                        parentParamName, propertyName, propertyType, propertyValue, knownConstructorFields);
            }
        } catch (Exception e) {
            throw new RuntimeException("Failed to write input fields for constructor", e);
        }
    }
private static void recurseBeanCreationParams ( List < UberField > uberFields , Class < ? > beanType , ActionDescriptor annotatedParameters , ActionInputParameter annotatedParameter , Object currentCallValue , String parentParamName , Set < String > knownFields ) { // TODO collection, map and object node creation are only describable by an annotation, not via type reflection if ( ObjectNode . class . isAssignableFrom ( beanType ) || Map . class . isAssignableFrom ( beanType ) || Collection . class . isAssignableFrom ( beanType ) || beanType . isArray ( ) ) { return ; // use @Input(include) to list parameter names, at least? Or mix with hdiv's form builder? } try { Constructor [ ] constructors = beanType . getConstructors ( ) ; // find default ctor Constructor constructor = PropertyUtils . findDefaultCtor ( constructors ) ; // find ctor with JsonCreator ann if ( constructor == null ) { constructor = PropertyUtils . findJsonCreator ( constructors , JsonCreator . class ) ; } Assert . notNull ( constructor , "no default constructor or JsonCreator found for type " + beanType . getName ( ) ) ; int parameterCount = constructor . getParameterTypes ( ) . length ; if ( parameterCount > 0 ) { Annotation [ ] [ ] annotationsOnParameters = constructor . getParameterAnnotations ( ) ; Class [ ] parameters = constructor . getParameterTypes ( ) ; int paramIndex = 0 ; for ( Annotation [ ] annotationsOnParameter : annotationsOnParameters ) { for ( Annotation annotation : annotationsOnParameter ) { if ( JsonProperty . class == annotation . annotationType ( ) ) { JsonProperty jsonProperty = ( JsonProperty ) annotation ; // TODO use required attribute of JsonProperty for required fields String paramName = jsonProperty . value ( ) ; Class parameterType = parameters [ paramIndex ] ; Object propertyValue = PropertyUtils . getPropertyOrFieldValue ( currentCallValue , paramName ) ; MethodParameter methodParameter = new MethodParameter ( constructor , paramIndex ) ; addUberFieldsForMethodParameter ( uberFields , methodParameter , annotatedParameter , annotatedParameters , parentParamName , paramName , parameterType , propertyValue , knownFields ) ; paramIndex ++ ; // increase for each @JsonProperty } } } Assert . isTrue ( parameters . length == paramIndex , "not all constructor arguments of @JsonCreator " + constructor . getName ( ) + " are annotated with @JsonProperty" ) ; } Set < String > knownConstructorFields = new HashSet < String > ( uberFields . size ( ) ) ; for ( UberField sirenField : uberFields ) { knownConstructorFields . add ( sirenField . getName ( ) ) ; } // TODO support Option provider by other method args? Map < String , PropertyDescriptor > propertyDescriptors = PropertyUtils . getPropertyDescriptors ( beanType ) ; // add input field for every setter for ( PropertyDescriptor propertyDescriptor : propertyDescriptors . values ( ) ) { final Method writeMethod = propertyDescriptor . getWriteMethod ( ) ; String propertyName = propertyDescriptor . getName ( ) ; if ( writeMethod == null || knownFields . contains ( parentParamName + propertyName ) ) { continue ; } final Class < ? > propertyType = propertyDescriptor . getPropertyType ( ) ; Object propertyValue = PropertyUtils . getPropertyOrFieldValue ( currentCallValue , propertyName ) ; MethodParameter methodParameter = new MethodParameter ( propertyDescriptor . getWriteMethod ( ) , 0 ) ; addUberFieldsForMethodParameter ( uberFields , methodParameter , annotatedParameter , annotatedParameters , parentParamName , propertyName , propertyType , propertyValue , knownConstructorFields ) ; } } catch ( Exception e ) { throw new RuntimeException ( "Failed to write input fields for constructor" , e ) ; } }
Renders input fields for bean properties of bean to add or update or patch.

@param uberFields
to add to
@param beanType
to render
@param annotatedParameters
which describes the method
@param annotatedParameter
which requires the bean
@param currentCallValue
sample call value
Renders input fields for bean properties of bean to add or update or patch .