private List<SirenField> toSirenFields(ActionDescriptor actionDescriptor) { List<SirenField> ret = new ArrayList<SirenField>(); if (actionDescriptor.hasRequestBody()) { recurseBeanCreationParams(ret, actionDescriptor.getRequestBody() .getParameterType(), actionDescriptor, actionDescriptor.getRequestBody(), actionDescriptor .getRequestBody() .getValue(), "", Collections.<String>emptySet()); } else { Collection<String> paramNames = actionDescriptor.getRequestParamNames(); for (String paramName : paramNames) { ActionInputParameter inputParameter = actionDescriptor.getActionInputParameter(paramName); Object[] possibleValues = inputParameter.getPossibleValues(actionDescriptor); ret.add(createSirenField(paramName, inputParameter.getValueFormatted(), inputParameter, possibleValues)); } } return ret; }
private void writeHydraVariableMapping(JsonGenerator jgen, @Nullable ActionDescriptor annotatedParameters, Collection<String> variableNames) throws IOException { if (annotatedParameters != null) { for (String variableName : variableNames) { // TODO: find also @Input ActionInputParameter annotatedParameter = annotatedParameters.getActionInputParameter(variableName); // TODO access @Input parameter, too // only unsatisfied parameters become hydra variables if (annotatedParameter != null && annotatedParameter.getValue() == null) { jgen.writeStartObject(); jgen.writeStringField("@type", "hydra:IriTemplateMapping"); jgen.writeStringField("hydra:variable", annotatedParameter.getParameterName()); jgen.writeBooleanField("hydra:required", annotatedParameter .isRequired()); jgen.writeStringField("hydra:property", getExposedPropertyOrParamName(annotatedParameter)); jgen.writeEndObject(); } } } }
private void writeSupportedProperty(JsonGenerator jgen, String currentVocab, ActionInputParameter actionInputParameter, String propertyName, @SuppressWarnings("unused") Object[] possiblePropertyValues) throws IOException { jgen.writeStartObject(); if (actionInputParameter.hasValue() || actionInputParameter.hasInputConstraints()) { // jgen.writeArrayFieldStart("@type"); // jgen.writeString("hydra:SupportedProperty"); jgen.writeStringField(JsonLdKeywords.AT_TYPE, getPropertyOrClassNameInVocab(currentVocab, "PropertyValueSpecification", LdContextFactory.HTTP_SCHEMA_ORG, "schema:")); //jgen.writeEndArray(); } jgen.writeStringField("hydra:property", propertyName); writePossiblePropertyValues(jgen, currentVocab, actionInputParameter, possiblePropertyValues); jgen.writeEndObject(); }
/** * Gets exposed property or parameter name. * * @param inputParameter for exposure * @return property name */ private String getExposedPropertyOrParamName(ActionInputParameter inputParameter) { final Expose expose = inputParameter.getAnnotation(Expose.class); String property; if (expose != null) { property = expose.value(); } else { property = inputParameter.getParameterName(); } return property; }
Class<?> parameterType = requestBody.getParameterType(); recurseBeanProperties(parameterType, actionDescriptor, requestBody, requestBody.getValue(), ""); } else { // plain parameter list Collection<String> requestParams = actionDescriptor.getRequestParamNames(); ActionInputParameter actionInputParameter = actionDescriptor.getActionInputParameter(requestParamName); Object[] possibleValues = actionInputParameter.getPossibleValues(actionDescriptor); if (actionInputParameter.isArrayOrCollection()) { appendSelectMulti(requestParamName, possibleValues, actionInputParameter); } else { if (actionInputParameter.isArrayOrCollection()) { Object[] callValues = actionInputParameter.getValues(); int items = callValues.length; for (int i = 0; i < items; i++) { .isReadOnly(requestParamName)); // not readonly String callValueFormatted = actionInputParameter.getValueFormatted(); appendInput(requestParamName, actionInputParameter, callValueFormatted, actionInputParameter .isReadOnly(requestParamName)); // not readonly
if (actionInputParameter.isIncluded(paramName)) { actionInputParameter.getPossibleValues( constructor, paramIndex, actionDescriptor); Object[] callValues = actionInputParameter.getValues(); int items = callValues.length; for (int i = 0; i < items; i++) { value = null; recurseBeanProperties(actionInputParameter.getParameterType(), actionDescriptor, actionInputParameter, value, parentParamName); ActionInputParameter propertySetterInputParameter = new SpringActionInputParameter(methodParameter, propertyValue); final Object[] possibleValues = actionInputParameter.getPossibleValues(propertyDescriptor .getWriteMethod(), 0, actionDescriptor); appendInputOrSelect(actionInputParameter, propertyName, propertySetterInputParameter, possibleValues); } else if (actionInputParameter.isArrayOrCollection()) { Object[] callValues = actionInputParameter.getValues(); int items = callValues.length; for (int i = 0; i < items; i++) { recurseBeanProperties(actionInputParameter.getParameterType(), actionDescriptor, actionInputParameter, value, parentParamName);
if (actionInputParameter.isArrayOrCollection()) { jgen.writeBooleanField(getPropertyOrClassNameInVocab(currentVocab, "multipleValues", LdContextFactory.HTTP_SCHEMA_ORG, "schema:"), true); final Map<String, Object> inputConstraints = actionInputParameter.getInputConstraints(); if (actionInputParameter.hasValue()) { if (actionInputParameter.isArrayOrCollection()) { Object[] callValues = actionInputParameter.getValues(); Class<?> componentType = callValues.getClass() .getComponentType(); LdContextFactory.HTTP_SCHEMA_ORG, "schema:")); writeScalarValue(jgen, actionInputParameter.getValue(), actionInputParameter .getParameterType());
String nextPropertyPathLevel = propertyPath.isEmpty() ? annotatedParameter.getParameterName() : propertyPath + '.' + annotatedParameter.getParameterName(); Class<?> parameterType = annotatedParameter.getParameterType(); if (DataType.isSingleValueType(parameterType)) { final Object[] possiblePropertyValues = rootParameter.getPossibleValues(allRootParameters); if (rootParameter.isIncluded(nextPropertyPathLevel) && !rootParameter.isExcluded (nextPropertyPathLevel)) { writeSupportedProperty(jgen, currentVocab, annotatedParameter, annotatedParameter.getParameterName(), possiblePropertyValues); jgen.writeStringField("hydra:property", annotatedParameter.getParameterName()); } else { if (List.class.isAssignableFrom(parameterType)) { Type genericParameterType = annotatedParameter.getGenericParameterType(); if (genericParameterType instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) genericParameterType; .getParameterName());
private void addSirenFieldsForMethodParameter(List<SirenField> sirenFields, MethodParameter methodParameter, ActionInputParameter annotatedParameter, ActionDescriptor annotatedParameters, String parentParamName, String paramName, Class parameterType, Object propertyValue, Set<String> knownFields) { if (DataType.isSingleValueType(parameterType) || DataType.isArrayOrCollection(parameterType)) { if (annotatedParameter.isIncluded(paramName) && !knownFields.contains(parentParamName + paramName)) { ActionInputParameter constructorParamInputParameter = new SpringActionInputParameter(methodParameter, propertyValue); final Object[] possibleValues = annotatedParameter.getPossibleValues(methodParameter, annotatedParameters); // dot-separated property path as field name SirenField sirenField = createSirenField(parentParamName + paramName, propertyValue, constructorParamInputParameter, possibleValues); sirenFields.add(sirenField); } } else { Object callValueBean; if (propertyValue instanceof Resource) { callValueBean = ((Resource) propertyValue).getContent(); } else { callValueBean = propertyValue; } recurseBeanCreationParams(sirenFields, parameterType, annotatedParameters, annotatedParameter, callValueBean, paramName + ".", knownFields); } }
private void appendInput(String requestParamName, ActionInputParameter actionInputParameter, Object value, boolean readOnly) throws IOException { if (actionInputParameter.isRequestBody()) { // recurseBeanProperties does that throw new IllegalArgumentException("cannot append input field for requestBody"); Type htmlInputFieldType = actionInputParameter.getHtmlInputFieldType(); Assert.notNull(htmlInputFieldType); String val = value == null ? "" : value.toString(); if (actionInputParameter.hasInputConstraints()) { for (Map.Entry<String, Object> inputConstraint : actionInputParameter.getInputConstraints() .entrySet()) { attrs.and(inputConstraint.getKey(), inputConstraint.getValue()
final Class<?> clazz = requestBodyInputParameter.getParameterType(); final Expose classExpose = clazz.getAnnotation(Expose.class); final String typeName; typeName = classExpose.value(); } else { typeName = requestBodyInputParameter.getParameterType() .getSimpleName(); requestBodyInputParameter, requestBodyInputParameter.getValue(), "");
/** * Appends simple input or select, depending on availability of possible values. * * @param parentInputParameter * the parent during bean recursion * @param paramName * of the child input parameter * @param childInputParameter * the current input to be rendered * @param possibleValues * suitable for childInputParameter * @throws IOException */ private void appendInputOrSelect(ActionInputParameter parentInputParameter, String paramName, ActionInputParameter childInputParameter, Object[] possibleValues) throws IOException { if (possibleValues.length > 0) { if (childInputParameter.isArrayOrCollection()) { // TODO multiple formatted callvalues appendSelectMulti(paramName, possibleValues, childInputParameter); } else { appendSelectOne(paramName, possibleValues, childInputParameter); } } else { appendInput(paramName, childInputParameter, childInputParameter.getValue(), parentInputParameter.isReadOnly(paramName)); } }
String propertyValueAsString = propertyValue == null ? null : propertyValue .toString(); Type htmlInputFieldType = inputParameter.getHtmlInputFieldType(); List<SirenFieldValue> sirenPossibleValues = new ArrayList<SirenFieldValue>(); String type; if (inputParameter.isArrayOrCollection()) { type = "checkbox"; for (Object possibleValue : possibleValues) { boolean selected = ObjectUtils.containsElement( inputParameter.getValues(), possibleValue);
@Override public String getDocumentationUrl(ActionInputParameter annotatedParameter, Object content) { return defaultUrlPrefix + annotatedParameter.getParameterName(); }
@Test public void testActionDescriptorForRequestBody() { final Affordance affordance = AffordanceBuilder.linkTo(AffordanceBuilder.methodOn(DummyController.class) .updateThing(1, (Thing) null)) .rel("event") .build(); Assert.assertEquals("Link: <http://example.com/things/1>; rel=\"event\"", affordance.toString()); final ActionDescriptor actionDescriptor = affordance.getActionDescriptors() .get(0); final ActionInputParameter thingParameter = actionDescriptor.getRequestBody(); Assert.assertEquals("Thing", ((Class) thingParameter.getGenericParameterType()).getSimpleName()); Assert.assertThat(thingParameter.isRequestBody(), Matchers.is(true)); Assert.assertEquals("updateThing", actionDescriptor.getActionName()); }
ActionInputParameter parameterValue = actionDescriptor.getActionInputParameter(paramName); if (parameterValue != null) { from.add(parameterValue.getValue());
@Test public void testActionDescriptorForRequestParams() { final Affordance affordance = AffordanceBuilder.linkTo(AffordanceBuilder.methodOn(DummyController.class) .updateThing(1, (EventStatusType) null)) .rel("eventStatus") .build(); Assert.assertEquals("Link-Template: <http://example.com/things/1/eventStatus{?eventStatus}>; " + "rel=\"eventStatus\"", affordance.toString()); final ActionDescriptor actionDescriptor = affordance.getActionDescriptors() .get(0); Assert.assertThat((EventStatusType[]) actionDescriptor.getActionInputParameter("eventStatus") .getPossibleValues(actionDescriptor), Matchers.arrayContainingInAnyOrder( EventStatusType.EVENT_CANCELLED, EventStatusType.EVENT_POSTPONED, EventStatusType.EVENT_RESCHEDULED, EventStatusType.EVENT_SCHEDULED)); Assert.assertEquals("updateThing", actionDescriptor.getActionName()); }
/** * Determines if the affordance has unsatisfied required variables. This allows to decide if the affordance can also * be treated as a plain Link without template variables if the caller omits all optional variables. Serializers can * use this to render it as a resource with optional search features. * * @return true if the affordance has unsatisfied required variables */ @JsonIgnore public boolean hasUnsatisfiedRequiredVariables() { for (ActionDescriptor actionDescriptor : actionDescriptors) { Map<String, ActionInputParameter> requiredParameters = actionDescriptor.getRequiredParameters(); for (ActionInputParameter annotatedParameter : requiredParameters.values()) { if (!annotatedParameter.hasValue()) { return true; } } } return false; }
private void appendSelectMulti(String requestParamName, Object[] possibleValues, ActionInputParameter actionInputParameter) throws IOException { beginDiv(OptionalAttributes.attr("class", formGroupClass)); Object[] actualValues = actionInputParameter.getValues(); final Object aCallValue; if (actualValues.length > 0) { aCallValue = actualValues[0]; } else { aCallValue = null; } String documentationUrl = documentationProvider.getDocumentationUrl(actionInputParameter, aCallValue); writeLabelWithDoc(requestParamName, requestParamName, documentationUrl); beginSelect(requestParamName, requestParamName, possibleValues.length, OptionalAttributes.attr("multiple", "multiple") .and("class", formControlClass)); for (Object possibleValue : possibleValues) { if (ObjectUtils.containsElement(actualValues, possibleValue)) { option(possibleValue.toString(), attr("selected", "selected")); } else { option(possibleValue.toString()); } } endForm(); endDiv(); }
Class<?> parameterType = requestBody.getParameterType(); recurseBeanProperties(parameterType, actionDescriptor, requestBody, requestBody.getValue(), ""); } else { // plain parameter list Collection<String> requestParams = actionDescriptor.getRequestParamNames(); ActionInputParameter actionInputParameter = actionDescriptor.getActionInputParameter(requestParamName); Object[] possibleValues = actionInputParameter.getPossibleValues(actionDescriptor); if (actionInputParameter.isArrayOrCollection()) { appendSelectMulti(requestParamName, possibleValues, actionInputParameter); } else { if (actionInputParameter.isArrayOrCollection()) { Object[] callValues = actionInputParameter.getValues(); int items = callValues.length; for (int i = 0; i < items; i++) { .isReadOnly(requestParamName)); // not readonly String callValueFormatted = actionInputParameter.getValueFormatted(); appendInput(requestParamName, actionInputParameter, callValueFormatted, actionInputParameter .isReadOnly(requestParamName)); // not readonly