use of com.linkedin.jersey.core.util.MultivaluedMap in project rest.li by linkedin.
the class BatchGetRequestBuilderTest method testComplexKeyBatching.
@SuppressWarnings({ "unchecked", "rawtypes" })
@Test
public void testComplexKeyBatching() throws URISyntaxException, PathSegmentSyntaxException {
String expectedProtocol1Uri = "/?fields=id,message&ids%5B0%5D.$params.id=1&ids%5B0%5D.$params.message=paramMessage1&ids%5B0%5D.id=1&ids%5B0%5D.message=keyMessage1&ids%5B1%5D.$params.id=2&ids%5B1%5D.$params.message=paramMessage2&ids%5B1%5D.id=2&ids%5B1%5D.message=keyMessage2&ids%5B2%5D.$params.id=3&ids%5B2%5D.$params.message=paramMessage3&ids%5B2%5D.id=3&ids%5B2%5D.message=keyMessage3¶m1=value1¶m2=value2";
ComplexResourceKey<TestRecord, TestRecord> complexKey1 = buildComplexKey(1L, "keyMessage1", 1L, "paramMessage1");
ComplexResourceKey<TestRecord, TestRecord> complexKey2 = buildComplexKey(2L, "keyMessage2", 2L, "paramMessage2");
ComplexResourceKey<TestRecord, TestRecord> complexKey3 = buildComplexKey(3L, "keyMessage3", 3L, "paramMessage3");
BatchGetRequestBuilder<ComplexResourceKey<TestRecord, TestRecord>, TestRecord> batchRequestBuilder1 = new BatchGetRequestBuilder<>("/", TestRecord.class, _complexResourceSpec, RestliRequestOptions.DEFAULT_OPTIONS);
ComplexResourceKey<TestRecord, TestRecord>[] complexKeys1 = new ComplexResourceKey[] { complexKey1, complexKey2 };
batchRequestBuilder1.ids(complexKeys1).fields(FIELDS.id()).setParam("param2", "value2").setParam("param1", "value1");
BatchGetRequestBuilder<ComplexResourceKey<TestRecord, TestRecord>, TestRecord> batchRequestBuilder2 = new BatchGetRequestBuilder<>("/", TestRecord.class, _complexResourceSpec, RestliRequestOptions.DEFAULT_OPTIONS);
ComplexResourceKey<TestRecord, TestRecord>[] complexKeys2 = new ComplexResourceKey[] { complexKey2, complexKey3 };
batchRequestBuilder2.ids(complexKeys2).fields(FIELDS.id(), FIELDS.message()).setParam("param1", "value1").setParam("param2", "value2");
BatchGetKVRequest<ComplexResourceKey<TestRecord, TestRecord>, TestRecord> batchRequest1 = batchRequestBuilder1.buildKV();
BatchGetKVRequest<ComplexResourceKey<TestRecord, TestRecord>, TestRecord> batchRequest2 = batchRequestBuilder2.buildKV();
@SuppressWarnings("unchecked") BatchGetKVRequest<ComplexResourceKey<TestRecord, TestRecord>, TestRecord> batchingRequest = BatchGetRequestBuilder.batchKV(Arrays.asList(batchRequest1, batchRequest2));
URI actualProtocol1Uri = RestliUriBuilderUtil.createUriBuilder(batchingRequest, AllProtocolVersions.RESTLI_PROTOCOL_1_0_0.getProtocolVersion()).build();
MultivaluedMap actualParams = UriComponent.decodeQuery(actualProtocol1Uri, true);
MultivaluedMap expectedUriParams = UriComponent.decodeQuery(URI.create(expectedProtocol1Uri), true);
DataMap expectedParamsDataMap = null;
DataMap actualParamsDataMap = null;
try {
expectedParamsDataMap = QueryParamsDataMap.parseDataMapKeys(expectedUriParams);
actualParamsDataMap = QueryParamsDataMap.parseDataMapKeys(actualParams);
} catch (PathSegmentSyntaxException e) {
// Should never happen
Assert.fail("Failed to parse data map keys!");
}
Assert.assertEquals(actualProtocol1Uri.getPath(), "/");
// Apparently due to using set to compact the list of ids in
// BatchGetRequestBuilder.batch() the order of the parameters on the url is no longer
// reliable.
DataList actualIds = (DataList) actualParamsDataMap.remove(RestConstants.QUERY_BATCH_IDS_PARAM);
DataList expectedIds = (DataList) expectedParamsDataMap.remove(RestConstants.QUERY_BATCH_IDS_PARAM);
Assert.assertEquals(new HashSet<>(actualIds), new HashSet<>(expectedIds));
Assert.assertEquals(actualParamsDataMap, expectedParamsDataMap);
Assert.assertEquals(batchingRequest.getBaseUriTemplate(), batchRequest1.getBaseUriTemplate());
Assert.assertEquals(batchingRequest.getPathKeys(), batchRequest1.getPathKeys());
Assert.assertEquals(batchingRequest.getFields(), new HashSet<>(Arrays.asList(FIELDS.id(), FIELDS.message())));
Assert.assertEquals(batchingRequest.getObjectIds(), new HashSet<Object>(Arrays.asList(complexKey1, complexKey2, complexKey3)));
String expectedProtocol2Uri = "/?fields=id,message&ids=List(($params:(id:1,message:paramMessage1),id:1,message:keyMessage1),($params:(id:2,message:paramMessage2),id:2,message:keyMessage2),($params:(id:3,message:paramMessage3),id:3,message:keyMessage3))¶m1=value1¶m2=value2";
URI actualProtocol2Uri = RestliUriBuilderUtil.createUriBuilder(batchingRequest, AllProtocolVersions.RESTLI_PROTOCOL_2_0_0.getProtocolVersion()).build();
Assert.assertEquals(actualProtocol2Uri.getPath(), "/");
actualParams = UriComponent.decodeQuery(actualProtocol2Uri, true);
MultivaluedMap expectedParams = UriComponent.decodeQuery(URI.create(expectedProtocol2Uri), true);
// we can't compare the query param "ids" directly as ID ordering is not preserved while batching in
// BatchGetRequestBuilder.batch()
Assert.assertEquals(actualParams.get("ids").size(), 1);
Assert.assertEquals(actualParams.get("ids").size(), expectedParams.get("ids").size());
// parse out the "ids" param into a DataList and then convert it into a set
String actualProtocol2IdsAsString = actualParams.remove("ids").get(0);
String expectedProtocol2IdsAsString = expectedParams.remove("ids").get(0);
DataList actualProtocol2Ids = (DataList) URIElementParser.parse(actualProtocol2IdsAsString);
DataList expectedProtocol2Ids = (DataList) URIElementParser.parse(expectedProtocol2IdsAsString);
Assert.assertEquals(new HashSet<>(actualProtocol2Ids.values()), new HashSet<>(expectedProtocol2Ids.values()));
// apart from the "ids" fields everything else should be the same
Assert.assertEquals(actualParams, expectedParams);
}
use of com.linkedin.jersey.core.util.MultivaluedMap in project rest.li by linkedin.
the class UriComponent method decodeQuery.
/**
* Decode the query component of a URI.
*
* @param q the query component in encoded form.
* @param decode true of the query parameters of the query component
* should be in decoded form.
* @return the multivalued map of query parameters.
*/
public static MultivaluedMap decodeQuery(String q, boolean decode) {
MultivaluedMap queryParameters = new MultivaluedMap();
if (q == null || q.length() == 0) {
return queryParameters;
}
int s = 0, e = 0;
do {
e = q.indexOf('&', s);
if (e == -1) {
decodeQueryParam(queryParameters, q.substring(s), decode);
} else if (e > s) {
decodeQueryParam(queryParameters, q.substring(s, e), decode);
}
s = e + 1;
} while (s > 0 && s < q.length());
return queryParameters;
}
use of com.linkedin.jersey.core.util.MultivaluedMap in project rest.li by linkedin.
the class UriComponent method decodeMatrix.
/**
* Decode the matrix component of a URI path segment.
*
* @param pathSegment the path segment component in encoded form.
* @param decode true if the matrix parameters of the path segment component
* should be in decoded form.
* @return the multivalued map of matrix parameters.
*/
public static MultivaluedMap decodeMatrix(String pathSegment, boolean decode) {
MultivaluedMap matrixMap = new MultivaluedMap();
// Skip over path segment
int s = pathSegment.indexOf(';') + 1;
if (s == 0 || s == pathSegment.length()) {
return matrixMap;
}
int e = 0;
do {
e = pathSegment.indexOf(';', s);
if (e == -1) {
decodeMatrixParam(matrixMap, pathSegment.substring(s), decode);
} else if (e > s) {
decodeMatrixParam(matrixMap, pathSegment.substring(s, e), decode);
}
s = e + 1;
} while (s > 0 && s < pathSegment.length());
return matrixMap;
}
use of com.linkedin.jersey.core.util.MultivaluedMap in project rest.li by linkedin.
the class BatchGetRequestBuilderTest method testUriGeneration.
private static void testUriGeneration(Request<?> request, String protocol1UriString, String protocol2UriString) throws URISyntaxException {
ProtocolVersion protocol1 = AllProtocolVersions.RESTLI_PROTOCOL_1_0_0.getProtocolVersion();
ProtocolVersion protocol2 = AllProtocolVersions.RESTLI_PROTOCOL_2_0_0.getProtocolVersion();
URI protocol1Uri = RestliUriBuilderUtil.createUriBuilder(request, protocol1).build();
URI protocol2Uri = RestliUriBuilderUtil.createUriBuilder(request, protocol2).build();
// V1:
MultivaluedMap actualQueryParamMapV1 = UriComponent.decodeQuery(protocol1Uri, true);
MultivaluedMap expectedQueryParamMapV1 = UriComponent.decodeQuery(new URI(protocol1UriString), true);
assertProtocolURIsMatch(actualQueryParamMapV1, expectedQueryParamMapV1, "Protocol 1");
// V2:
MultivaluedMap actualQueryParamMapV2 = UriComponent.decodeQuery(protocol2Uri, true);
MultivaluedMap expectedQueryParamMapV2 = UriComponent.decodeQuery(new URI(protocol2UriString), true);
assertProtocolURIsMatch(actualQueryParamMapV2, expectedQueryParamMapV2, "Protocol 2");
}
use of com.linkedin.jersey.core.util.MultivaluedMap in project rest.li by linkedin.
the class DefaultDocumentationRequestHandler method processDocumentationRequest.
@SuppressWarnings("fallthrough")
private RestResponse processDocumentationRequest(Request request) {
final String path = request.getURI().getRawPath();
final List<UriComponent.PathSegment> pathSegments = UriComponent.decodePath(path, true);
String prefixSegment = null;
String actionSegment = null;
String typeSegment = null;
String objectSegment = null;
switch(pathSegments.size()) {
case 5:
objectSegment = pathSegments.get(4).getPath();
case 4:
typeSegment = pathSegments.get(3).getPath();
case 3:
actionSegment = pathSegments.get(2).getPath();
case 2:
prefixSegment = pathSegments.get(1).getPath();
}
assert (DOC_PREFIX.equals(prefixSegment) || (HttpMethod.valueOf(request.getMethod()) == HttpMethod.OPTIONS));
final ByteArrayOutputStream out = new ByteArrayOutputStream(BAOS_BUFFER_SIZE);
final RenderContext renderContext = new RenderContext(out, request.getHeaders());
final RestLiDocumentationRenderer renderer;
if (HttpMethod.valueOf(request.getMethod()) == HttpMethod.OPTIONS) {
renderer = _jsonRenderer;
renderer.renderResource(prefixSegment, renderContext);
} else if (HttpMethod.valueOf(request.getMethod()) == HttpMethod.GET) {
if (!DOC_VIEW_DOCS_ACTION.equals(actionSegment)) {
throw createRoutingError(path);
}
final MultivaluedMap queryMap = UriComponent.decodeQuery(request.getURI().getQuery(), false);
final List<String> formatList = queryMap.get("format");
if (formatList == null) {
renderer = _htmlRenderer;
} else if (formatList.size() > 1) {
throw new RoutingException(String.format("\"format\" query parameter must be unique, where multiple are specified: %s", Arrays.toString(formatList.toArray())), HttpStatus.S_400_BAD_REQUEST.getCode());
} else {
renderer = (formatList.contains(DOC_JSON_FORMAT) ? _jsonRenderer : _htmlRenderer);
}
if (renderer == _htmlRenderer) {
_htmlRenderer.setFormatUriProvider(docFormat -> {
if (RestLiDocumentationRenderer.DocumentationFormat.JSON.equals(docFormat)) {
return UriBuilder.fromUri(_config.getServerNodeUri()).path(request.getURI().getPath()).queryParam("format", DOC_JSON_FORMAT).build();
}
return null;
});
}
try {
if (typeSegment == null || typeSegment.isEmpty()) {
renderer.renderHome(renderContext);
} else {
if (DOC_RESOURCE_TYPE.equals(typeSegment)) {
if (objectSegment == null || objectSegment.isEmpty()) {
renderer.renderResourceHome(renderContext);
} else {
renderer.renderResource(objectSegment, renderContext);
}
} else if (DOC_DATA_TYPE.equals(typeSegment)) {
if (objectSegment == null || objectSegment.isEmpty()) {
renderer.renderDataModelHome(renderContext);
} else {
renderer.renderDataModel(objectSegment, renderContext);
}
} else {
throw createRoutingError(path);
}
}
} catch (RuntimeException e) {
if (!renderer.handleException(e, renderContext)) {
throw e;
}
}
} else {
throw new RoutingException(HttpStatus.S_405_METHOD_NOT_ALLOWED.getCode());
}
return new RestResponseBuilder().setStatus(HttpStatus.S_200_OK.getCode()).setHeader(RestConstants.HEADER_CONTENT_TYPE, renderer.getMIMEType()).setEntity(out.toByteArray()).build();
}
Aggregations