use of com.linkedin.restli.common.ResourceMethod in project rest.li by linkedin.
the class RequestBuilderSpecGenerator method generateRootRequestBuilder.
private RootBuilderSpec generateRootRequestBuilder(RootBuilderSpec parentRootBuilder, ResourceSchema resource, String sourceFile, Map<String, String> pathKeyTypes) throws IOException {
ValidationResult validationResult = ValidateDataAgainstSchema.validate(resource.data(), resource.schema(), new ValidationOptions());
if (!validationResult.isValid()) {
throw new IllegalArgumentException(String.format("Resource validation error. Resource File '%s', Error Details '%s'", sourceFile, validationResult.toString()));
}
String packageName = resource.getNamespace();
String resourceName = CodeUtil.capitalize(resource.getName());
String className;
if (_version == RestliVersion.RESTLI_2_0_0) {
className = getBuilderClassNameByVersion(RestliVersion.RESTLI_2_0_0, null, resource.getName(), true);
} else {
className = getBuilderClassNameByVersion(RestliVersion.RESTLI_1_0_0, null, resource.getName(), true);
}
RootBuilderSpec rootBuilderSpec = null;
if (resource.hasCollection()) {
rootBuilderSpec = new CollectionRootBuilderSpec(resource);
} else if (resource.hasSimple()) {
rootBuilderSpec = new SimpleRootBuilderSpec(resource);
} else if (resource.hasActionsSet()) {
rootBuilderSpec = new ActionSetRootBuilderSpec(resource);
} else {
log.warn("Ignoring unsupported association resource: " + resourceName);
return null;
}
rootBuilderSpec.setNamespace(packageName);
rootBuilderSpec.setClassName(className);
if (_version == RestliVersion.RESTLI_2_0_0) {
rootBuilderSpec.setBaseClassName("BuilderBase");
}
rootBuilderSpec.setSourceIdlName(sourceFile);
String resourcePath = getResourcePath(resource.getPath());
rootBuilderSpec.setResourcePath(resourcePath);
List<String> pathKeys = getPathKeys(resourcePath);
rootBuilderSpec.setPathKeys(pathKeys);
rootBuilderSpec.setParentRootBuilder(parentRootBuilder);
StringArray supportsList = null;
RestMethodSchemaArray restMethods = null;
FinderSchemaArray finders = null;
ResourceSchemaArray subresources = null;
ActionSchemaArray resourceActions = null;
ActionSchemaArray entityActions = null;
String keyClass = null;
if (resource.getCollection() != null) {
CollectionSchema collection = resource.getCollection();
String keyName = collection.getIdentifier().getName();
// Complex key is not supported
keyClass = collection.getIdentifier().getType();
pathKeyTypes.put(keyName, collection.getIdentifier().getType());
supportsList = collection.getSupports();
restMethods = collection.getMethods();
finders = collection.getFinders();
subresources = collection.getEntity().getSubresources();
resourceActions = collection.getActions();
entityActions = collection.getEntity().getActions();
} else if (resource.getSimple() != null) {
SimpleSchema simpleSchema = resource.getSimple();
keyClass = "Void";
supportsList = simpleSchema.getSupports();
restMethods = simpleSchema.getMethods();
subresources = simpleSchema.getEntity().getSubresources();
resourceActions = simpleSchema.getActions();
} else if (resource.getActionsSet() != null) {
ActionsSetSchema actionsSet = resource.getActionsSet();
resourceActions = actionsSet.getActions();
}
Set<ResourceMethod> supportedMethods = getSupportedMethods(supportsList);
if (!supportedMethods.isEmpty()) {
for (ResourceMethod resourceMethod : supportedMethods) {
validateResourceMethod(resource, resourceName, resourceMethod);
}
}
List<RootBuilderMethodSpec> restMethodSpecs = new ArrayList<>();
List<RootBuilderMethodSpec> finderSpecs = new ArrayList<>();
List<RootBuilderMethodSpec> resourceActionSpecs = new ArrayList<>();
List<RootBuilderMethodSpec> entityActionSpecs = new ArrayList<>();
List<RootBuilderSpec> subresourceSpecs = new ArrayList<>();
String schemaClass = resource.getSchema();
if (restMethods != null) {
restMethodSpecs = generateBasicMethods(rootBuilderSpec, keyClass, schemaClass, supportedMethods, restMethods, resourceName, pathKeys, pathKeyTypes);
}
if (finders != null) {
finderSpecs = generateFinders(rootBuilderSpec, finders, keyClass, schemaClass, resourceName, pathKeys, pathKeyTypes);
}
if (resourceActions != null) {
resourceActionSpecs = generateActions(rootBuilderSpec, resourceActions, keyClass, resourceName, pathKeys, pathKeyTypes);
}
if (entityActions != null) {
entityActionSpecs = generateActions(rootBuilderSpec, entityActions, keyClass, resourceName, pathKeys, pathKeyTypes);
}
if (subresources != null) {
subresourceSpecs = generateSubResources(sourceFile, rootBuilderSpec, subresources, pathKeyTypes);
}
// assign to rootBuilderClass
if (rootBuilderSpec instanceof CollectionRootBuilderSpec) {
CollectionRootBuilderSpec rootBuilder = (CollectionRootBuilderSpec) rootBuilderSpec;
rootBuilder.setRestMethods(restMethodSpecs);
rootBuilder.setFinders(finderSpecs);
rootBuilder.setResourceActions(resourceActionSpecs);
rootBuilder.setEntityActions(entityActionSpecs);
rootBuilder.setSubresources(subresourceSpecs);
} else if (rootBuilderSpec instanceof SimpleRootBuilderSpec) {
SimpleRootBuilderSpec rootBuilder = (SimpleRootBuilderSpec) rootBuilderSpec;
rootBuilder.setRestMethods(restMethodSpecs);
rootBuilder.setResourceActions(resourceActionSpecs);
rootBuilder.setSubresources(subresourceSpecs);
} else if (rootBuilderSpec instanceof ActionSetRootBuilderSpec) {
ActionSetRootBuilderSpec rootBuilder = (ActionSetRootBuilderSpec) rootBuilderSpec;
rootBuilder.setResourceActions(resourceActionSpecs);
}
registerBuilderSpec(rootBuilderSpec);
return rootBuilderSpec;
}
use of com.linkedin.restli.common.ResourceMethod in project rest.li by linkedin.
the class TestRestLiValidationFilter method testHandleProjection.
/**
* Ensures that the validation filter safely and correctly reacts to projections given a variety of resource types,
* resource methods, and projection masks. This was motivated by a bug that caused an NPE in the validation filter
* when the resource being queried was a {@link RestLiActions} resource and thus had no value class.
*/
@Test(dataProvider = "validateWithProjectionData")
@SuppressWarnings({ "unchecked" })
public void testHandleProjection(ResourceModel resourceModel, RestLiResponseData<RestLiResponseEnvelope> responseData, MaskTree projectionMask, boolean expectError) {
ResourceMethod resourceMethod = responseData.getResourceMethod();
when(filterRequestContext.getRequestData()).thenReturn(new RestLiRequestDataImpl.Builder().entity(makeTestRecord()).build());
when(filterRequestContext.getMethodType()).thenReturn(resourceMethod);
when(filterRequestContext.getFilterResourceModel()).thenReturn(new FilterResourceModelImpl(resourceModel));
when(filterRequestContext.getProjectionMask()).thenReturn(projectionMask);
when(filterResponseContext.getResponseData()).thenReturn((RestLiResponseData) responseData);
RestLiValidationFilter validationFilter = new RestLiValidationFilter();
try {
validationFilter.onRequest(filterRequestContext);
if (expectError) {
Assert.fail("Expected an error to be thrown on request in the validation filter, but none was thrown.");
}
} catch (RestLiServiceException e) {
if (expectError) {
Assert.assertEquals(e.getStatus(), HttpStatus.S_400_BAD_REQUEST);
return;
} else {
Assert.fail("An unexpected exception was thrown on request in the validation filter.", e);
}
}
validationFilter.onResponse(filterRequestContext, filterResponseContext);
}
use of com.linkedin.restli.common.ResourceMethod in project rest.li by linkedin.
the class BaseResourceSpec method getImportsForMethods.
public List<String> getImportsForMethods() {
if (_imports == null) {
Set<String> imports = new TreeSet<>();
if (getActions().size() > 0) {
imports.add(ActionRequest.class.getName());
imports.add(ActionResponse.class.getName());
imports.add(ActionResponseDecoder.class.getName());
imports.add(DynamicRecordTemplate.class.getName());
imports.add(FieldDef.class.getName());
// Add action value class to imports
getActions().stream().forEach(actionMethodSpec -> {
if (!SpecUtils.checkIfShortNameConflictAndUpdateMapping(_importCheckConflict, ClassUtils.getShortClassName(actionMethodSpec.getValueClassName()), actionMethodSpec.getValueClassName())) {
imports.add(actionMethodSpec.getValueClassName());
actionMethodSpec.setUsingShortClassName(true);
}
if (actionMethodSpec.hasReturnTypeRef() && !SpecUtils.checkIfShortNameConflictAndUpdateMapping(_importCheckConflict, ClassUtils.getShortClassName(actionMethodSpec.getValueTypeRefClassName()), actionMethodSpec.getValueTypeRefClassName())) {
imports.add(actionMethodSpec.getValueTypeRefClassName());
actionMethodSpec.setUsingShortTypeRefClassName(true);
}
});
}
for (RestMethodSpec methodSpec : getRestMethods()) {
ResourceMethod method = ResourceMethod.fromString(methodSpec.getMethod());
switch(method) {
case GET:
imports.add(GetRequest.class.getName());
break;
case BATCH_GET:
imports.add(BatchGetEntityRequest.class.getName());
imports.add(BatchKVResponse.class.getName());
imports.add(EntityResponse.class.getName());
imports.add(BatchEntityResponseDecoder.class.getName());
break;
case CREATE:
imports.add(CreateIdRequest.class.getName());
imports.add(IdResponse.class.getName());
imports.add(IdResponseDecoder.class.getName());
if (methodSpec.returnsEntity()) {
imports.add(CreateIdEntityRequest.class.getName());
imports.add(IdEntityResponse.class.getName());
imports.add(IdEntityResponseDecoder.class.getName());
}
break;
case BATCH_CREATE:
imports.add(CollectionRequest.class.getName());
imports.add(BatchCreateIdRequest.class.getName());
imports.add(CreateIdStatus.class.getName());
imports.add(BatchCreateIdResponse.class.getName());
imports.add(BatchCreateIdDecoder.class.getName());
if (methodSpec.returnsEntity()) {
imports.add(BatchCreateIdEntityRequest.class.getName());
imports.add(CreateIdEntityStatus.class.getName());
imports.add(BatchCreateIdEntityResponse.class.getName());
imports.add(BatchCreateIdEntityDecoder.class.getName());
}
break;
case PARTIAL_UPDATE:
imports.add(PatchRequest.class.getName());
imports.add(PartialUpdateRequest.class.getName());
if (methodSpec.returnsEntity()) {
imports.add(PartialUpdateEntityRequest.class.getName());
imports.add(EntityResponseDecoder.class.getName());
}
break;
case BATCH_PARTIAL_UPDATE:
imports.add(PatchRequest.class.getName());
imports.add(BatchPartialUpdateRequest.class.getName());
imports.add(CollectionRequest.class.getName());
imports.add(UpdateStatus.class.getName());
imports.add(BatchKVResponse.class.getName());
imports.add(KeyValueRecordFactory.class.getName());
imports.add(KeyValueRecord.class.getName());
if (methodSpec.returnsEntity()) {
imports.add(BatchPartialUpdateEntityRequest.class.getName());
imports.add(UpdateEntityStatus.class.getName());
}
break;
case UPDATE:
imports.add(UpdateRequest.class.getName());
break;
case BATCH_UPDATE:
imports.add(BatchUpdateRequest.class.getName());
imports.add(BatchKVResponse.class.getName());
imports.add(KeyValueRecordFactory.class.getName());
imports.add(KeyValueRecord.class.getName());
imports.add(CollectionRequest.class.getName());
imports.add(UpdateStatus.class.getName());
break;
case DELETE:
imports.add(DeleteRequest.class.getName());
break;
case BATCH_DELETE:
imports.add(BatchDeleteRequest.class.getName());
imports.add(UpdateStatus.class.getName());
break;
case GET_ALL:
imports.add(GetAllRequest.class.getName());
imports.add(CollectionResponse.class.getName());
break;
default:
break;
}
}
if (!getFinders().isEmpty()) {
imports.add(FindRequest.class.getName());
imports.add(CollectionResponse.class.getName());
}
if (!getBatchFinders().isEmpty()) {
imports.add(BatchFindRequest.class.getName());
imports.add(BatchCollectionResponse.class.getName());
imports.add(BatchFinderCriteriaResult.class.getName());
}
// than complex key, etc.
if (_entityClassName == null) {
if (getEntityClass() == null) {
_entityClassName = Void.class.getSimpleName();
} else if (SpecUtils.checkIfShortNameConflictAndUpdateMapping(_importCheckConflict, getEntityClass().getClassName(), getEntityClass().getBindingName())) {
_entityClassName = getEntityClass().getFullName();
} else {
imports.add(getEntityClass().getFullName());
_entityClassName = getEntityClass().getClassName();
}
}
// Add param classes to imports
Stream.of(getRestMethods().stream().map(RestMethodSpec::getAllParameters).flatMap(List::stream), getActions().stream().map(ActionMethodSpec::getAllParameters).flatMap(List::stream), getFinders().stream().map(MethodSpec::getAllParameters).flatMap(List::stream), getBatchFinders().stream().map(MethodSpec::getAllParameters).flatMap(List::stream)).reduce(Stream::concat).orElseGet(Stream::empty).forEach(paramSpec -> {
if (!SpecUtils.checkIfShortNameConflictAndUpdateMapping(_importCheckConflict, ClassUtils.getShortClassName(paramSpec.getParamClassName()), paramSpec.getParamClassName())) {
imports.add(paramSpec.getParamClassName());
paramSpec.setUsingShortClassName(true);
}
if (paramSpec.hasParamTypeRef() && !SpecUtils.checkIfShortNameConflictAndUpdateMapping(_importCheckConflict, ClassUtils.getShortClassName(paramSpec.getParamTypeRefClassName()), paramSpec.getParamTypeRefClassName())) {
imports.add(paramSpec.getParamTypeRefClassName());
paramSpec.setUsingShortTypeRefClassName(true);
}
if (paramSpec.isArray() && !SpecUtils.checkIfShortNameConflictAndUpdateMapping(_importCheckConflict, ClassUtils.getShortClassName(paramSpec.getItemClassName()), paramSpec.getItemClassName())) {
imports.add(paramSpec.getItemClassName());
paramSpec.setUsingShortItemClassName(true);
}
});
// Sub resources are handled recursively
_imports = getResourceSpecificImports(imports);
}
return _imports.stream().filter(importClass -> !(importClass.startsWith(SpecUtils.JAVA_LANG_PREFIX) || SpecUtils.PRIMITIVE_CLASS_NAMES.contains(importClass))).collect(Collectors.toList());
}
use of com.linkedin.restli.common.ResourceMethod in project rest.li by linkedin.
the class BatchGetRequestBuilderTest method testBatchingWithNullProjectionFirst.
@Test
public void testBatchingWithNullProjectionFirst() {
BatchGetRequestBuilder<Integer, TestRecord> batchRequestBuilder1 = new BatchGetRequestBuilder<>("/", TestRecord.class, new ResourceSpecImpl(Collections.<ResourceMethod>emptySet(), Collections.<String, DynamicRecordMetadata>emptyMap(), Collections.<String, DynamicRecordMetadata>emptyMap(), Integer.class, null, null, null, Collections.<String, Object>emptyMap()), RestliRequestOptions.DEFAULT_OPTIONS);
batchRequestBuilder1.ids(1);
BatchGetRequestBuilder<Integer, TestRecord> batchRequestBuilder2 = new BatchGetRequestBuilder<>("/", TestRecord.class, new ResourceSpecImpl(Collections.<ResourceMethod>emptySet(), Collections.<String, DynamicRecordMetadata>emptyMap(), Collections.<String, DynamicRecordMetadata>emptyMap(), Integer.class, null, null, null, Collections.<String, Object>emptyMap()), RestliRequestOptions.DEFAULT_OPTIONS);
batchRequestBuilder2.ids(2, 3);
batchRequestBuilder2.fields(FIELDS.message());
BatchGetRequest<TestRecord> batchRequest1 = batchRequestBuilder1.build();
@SuppressWarnings("unchecked") BatchGetRequest<TestRecord> batchingRequest = BatchGetRequestBuilder.batch(Arrays.asList(batchRequest1, batchRequestBuilder2.build()));
Assert.assertEquals(batchingRequest.getBaseUriTemplate(), batchRequest1.getBaseUriTemplate());
Assert.assertEquals(batchingRequest.getPathKeys(), batchRequest1.getPathKeys());
Assert.assertEquals(batchingRequest.getFields(), Collections.emptySet());
Assert.assertEquals(batchingRequest.getObjectIds(), new HashSet<>(Arrays.asList(1, 2, 3)));
}
use of com.linkedin.restli.common.ResourceMethod in project rest.li by linkedin.
the class BatchGetRequestBuilderTest method testSimpleBatchingFailureWithDiffParams.
@Test
public void testSimpleBatchingFailureWithDiffParams() {
BatchGetRequestBuilder<Integer, TestRecord> batchRequestBuilder1 = new BatchGetRequestBuilder<>("/", TestRecord.class, new ResourceSpecImpl(Collections.<ResourceMethod>emptySet(), Collections.<String, DynamicRecordMetadata>emptyMap(), Collections.<String, DynamicRecordMetadata>emptyMap(), Integer.class, null, null, null, Collections.<String, Object>emptyMap()), RestliRequestOptions.DEFAULT_OPTIONS);
batchRequestBuilder1.ids(1, 2).fields(FIELDS.id()).setParam("param1", "value1");
BatchGetRequestBuilder<Integer, TestRecord> batchRequestBuilder2 = new BatchGetRequestBuilder<>("/", TestRecord.class, new ResourceSpecImpl(Collections.<ResourceMethod>emptySet(), Collections.<String, DynamicRecordMetadata>emptyMap(), Collections.<String, DynamicRecordMetadata>emptyMap(), Integer.class, null, null, null, Collections.<String, Object>emptyMap()), RestliRequestOptions.DEFAULT_OPTIONS);
batchRequestBuilder2.ids(2, 3).fields(FIELDS.id(), FIELDS.message()).setParam("param1", "value1").setParam("param2", "value2");
BatchGetRequest<TestRecord> batchRequest1 = batchRequestBuilder1.build();
BatchGetRequest<TestRecord> batchRequest2 = batchRequestBuilder2.build();
try {
@SuppressWarnings("unchecked") List<BatchGetRequest<TestRecord>> batchRequestsList = Arrays.asList(batchRequest1, batchRequest2);
BatchGetRequestBuilder.batch(batchRequestsList);
Assert.fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException ignored) {
// Expected
}
}
Aggregations