use of com.linkedin.data.schema.RecordDataSchema in project rest.li by linkedin.
the class ExampleRequestResponseGenerator method finder.
public ExampleRequestResponse finder(String name) {
FinderSchema finderSchema = _resourceSchema.getFinder(name);
if (finderSchema == null) {
throw new IllegalArgumentException("No such finder for resource: " + name);
}
RecordDataSchema metadataSchema = null;
if (finderSchema.hasMetadata()) {
metadataSchema = (RecordDataSchema) RestSpecCodec.textToSchema(finderSchema.getMetadata().getType(), _schemaResolver);
}
return buildRequestResponse(buildFinderRequest(finderSchema), buildFinderResult(metadataSchema), buildResourceMethodDescriptorForFinder(name));
}
use of com.linkedin.data.schema.RecordDataSchema in project rest.li by linkedin.
the class ExampleRequestResponseGenerator method generateFieldDefValue.
private Object generateFieldDefValue(FieldDef<?> fieldDef) {
Object value = _dataGenerator.buildData(fieldDef.getName(), fieldDef.getDataSchema());
DataSchema dereferencedDataSchema = fieldDef.getDataSchema().getDereferencedDataSchema();
if (!dereferencedDataSchema.isPrimitive()) {
switch(dereferencedDataSchema.getType()) {
case FIXED:
value = new FixedTemplatePlaceholder(value, (FixedDataSchema) dereferencedDataSchema);
break;
case ENUM:
// just use the string value already generated. Will be coerced by DataTemplateUtil.DynamicEnumCoercer.
break;
case ARRAY:
value = new ArrayTemplatePlaceholder<>((DataList) value, (ArrayDataSchema) dereferencedDataSchema, Object.class);
break;
case RECORD:
value = new RecordTemplatePlaceholder((DataMap) value, (RecordDataSchema) dereferencedDataSchema);
break;
case MAP:
value = new MapTemplatePlaceholder<>((DataMap) value, (MapDataSchema) dereferencedDataSchema, Object.class);
break;
case UNION:
value = new UnionTemplatePlaceholder(value, (UnionDataSchema) dereferencedDataSchema);
break;
case TYPEREF:
throw new IllegalStateException("TYPEREF should not be returned for a dereferenced byte. schema: " + fieldDef.getDataSchema());
default:
throw new IllegalStateException("Unrecognized enum value: " + dereferencedDataSchema.getType());
}
}
return value;
}
use of com.linkedin.data.schema.RecordDataSchema in project rest.li by linkedin.
the class TestExamplesGenerator method validateActionResponse.
private <T extends RecordTemplate> ValidationResult validateActionResponse(RestResponse response, Class<T> recordClass, ValidationOptions options) throws IOException {
final DataMap respData = _codec.bytesToMap(response.getEntity().copyBytes());
final FieldDef<T> responseFieldDef = new FieldDef<>(ActionResponse.VALUE_NAME, recordClass, DataTemplateUtil.getSchema(recordClass));
final RecordDataSchema recordDataSchema = DynamicRecordMetadata.buildSchema(ActionResponse.class.getName(), Collections.<FieldDef<?>>singletonList(responseFieldDef));
final ActionResponse<T> actionResp = new ActionResponse<>(respData, responseFieldDef, recordDataSchema);
final DataSchema recordSchema = DataTemplateUtil.getSchema(recordClass);
return ValidateDataAgainstSchema.validate(actionResp.getValue().data(), recordSchema, options);
}
use of com.linkedin.data.schema.RecordDataSchema in project rest.li by linkedin.
the class RestLiAnnotationReader method addActionResourceMethod.
/**
* Add the given action method to the given resource model, validating the method is a action before adding.
* @param model provides the model to add the method to.
* @param method provides the method to add to the model.
* @throws ResourceConfigException on validation errors.
*/
private static void addActionResourceMethod(final ResourceModel model, final Method method) {
Action actionAnno = method.getAnnotation(Action.class);
if (actionAnno == null) {
return;
}
String actionName = actionAnno.name();
List<Parameter<?>> parameters = getParameters(model, method, ResourceMethod.ACTION);
Class<?> returnClass = getActionReturnClass(model, method, actionAnno, actionName);
TyperefDataSchema returnTyperefSchema = getActionTyperefDataSchema(model, actionAnno, actionName);
validateActionReturnType(model, method, returnClass, returnTyperefSchema);
if (!Modifier.isPublic(method.getModifiers())) {
throw new ResourceConfigException(String.format("Resource '%s' contains non-public action method '%s'.", model.getName(), method.getName()));
}
RecordDataSchema recordDataSchema = DynamicRecordMetadata.buildSchema(method.getName(), parameters);
RecordDataSchema actionReturnRecordDataSchema;
FieldDef<?> returnFieldDef;
if (returnClass != Void.TYPE) {
@SuppressWarnings({ "unchecked", "rawtypes" }) FieldDef<?> nonVoidFieldDef = new FieldDef(ActionResponse.VALUE_NAME, returnClass, getDataSchema(returnClass, returnTyperefSchema));
returnFieldDef = nonVoidFieldDef;
actionReturnRecordDataSchema = DynamicRecordMetadata.buildSchema(ActionResponse.class.getName(), Collections.singleton((returnFieldDef)));
} else {
returnFieldDef = null;
actionReturnRecordDataSchema = DynamicRecordMetadata.buildSchema(ActionResponse.class.getName(), Collections.<FieldDef<?>>emptyList());
}
if (model.getResourceLevel() == ResourceLevel.ENTITY && actionAnno.resourceLevel() == ResourceLevel.COLLECTION) {
throw new ResourceConfigException(String.format("Resource '%s' is a simple resource, it cannot contain actions at resource level \"COLLECTION\".", model.getName()));
}
DataMap annotationsMap = ResourceModelAnnotation.getAnnotationsMap(method.getAnnotations());
addDeprecatedAnnotation(annotationsMap, method);
ResourceMethodDescriptor resourceMethodDescriptor = ResourceMethodDescriptor.createForAction(method, parameters, actionName, getActionResourceLevel(actionAnno, model), returnFieldDef, actionReturnRecordDataSchema, actionAnno.readOnly(), recordDataSchema, getInterfaceType(method), annotationsMap);
addServiceErrors(resourceMethodDescriptor, method);
addSuccessStatuses(resourceMethodDescriptor, method);
model.addResourceMethodDescriptor(resourceMethodDescriptor);
}
use of com.linkedin.data.schema.RecordDataSchema in project rest.li by linkedin.
the class ActionResponseBuilder method buildRestLiResponseData.
/**
* {@inheritDoc}
*
* @param result The result for a Rest.li ACTION method. It can be the return value for the ACTION itself, or the
* return value wrapped in an {@link ActionResult}.
*/
@Override
public RestLiResponseData<ActionResponseEnvelope> buildRestLiResponseData(Request request, RoutingResult routingResult, Object result, Map<String, String> headers, List<HttpCookie> cookies) {
final Object value;
final HttpStatus status;
if (result instanceof ActionResult) {
final ActionResult<?> actionResult = (ActionResult<?>) result;
value = actionResult.getValue();
status = actionResult.getStatus();
if (status == null) {
throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Unexpected null encountered. Null HttpStatus inside of an ActionResult returned by the resource method: " + routingResult.getResourceMethod());
}
// When it has an ActionResult<Void> type response, it should return null but not empty body record
if (routingResult.getResourceMethod().getActionReturnType() == Void.TYPE) {
return new RestLiResponseDataImpl<>(new ActionResponseEnvelope(status, null), headers, cookies);
}
} else {
// when value == null and return type is void, it is handled outside in RestLiResponseHandler
value = result;
status = HttpStatus.S_200_OK;
}
RecordDataSchema actionReturnRecordDataSchema = routingResult.getResourceMethod().getActionReturnRecordDataSchema();
final Object actionResponseValue;
if (value != null && RecordTemplate.class.isAssignableFrom(value.getClass()) && routingResult.getContext().isFillInDefaultsRequested()) {
RecordTemplate actionResponseRecordTemplate = (RecordTemplate) value;
DataMap dataMap = actionResponseRecordTemplate.data();
dataMap = (DataMap) ResponseUtils.fillInDataDefault(actionResponseRecordTemplate.schema(), dataMap);
Object valueWithDefault = null;
try {
valueWithDefault = (Object) value.getClass().getConstructor(DataMap.class).newInstance(dataMap);
} catch (Exception e) {
throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Unexpected error encountered. Can not create return value class " + value.getClass().getSimpleName() + " with default filled inside of an ActionResult returned by the resource method: " + routingResult.getResourceMethod());
}
actionResponseValue = valueWithDefault;
} else {
actionResponseValue = value;
}
@SuppressWarnings("unchecked") FieldDef<Object> actionReturnFieldDef = (FieldDef<Object>) routingResult.getResourceMethod().getActionReturnFieldDef();
final ActionResponse<?> actionResponse = new ActionResponse<>(actionResponseValue, actionReturnFieldDef, actionReturnRecordDataSchema);
return new RestLiResponseDataImpl<>(new ActionResponseEnvelope(status, actionResponse), headers, cookies);
}
Aggregations