Search in sources :

Example 16 with CompoundKey

use of com.linkedin.restli.common.CompoundKey in project rest.li by linkedin.

the class TestTyperefCustomDoubleAssociationKeyResource method testGet.

@Test(dataProvider = TestConstants.RESTLI_PROTOCOL_1_2_PREFIX + "requestOptionsDataProvider")
public void testGet(RestliRequestOptions requestOptions) throws RemoteInvocationException {
    HashMap<String, CompoundKey.TypeInfo> keyParts = new HashMap<String, CompoundKey.TypeInfo>();
    keyParts.put("src", new CompoundKey.TypeInfo(Double.class, Double.class));
    keyParts.put("dest", new CompoundKey.TypeInfo(Double.class, Double.class));
    GetRequestBuilder<CompoundKey, Message> getBuilder = new GetRequestBuilder<CompoundKey, Message>("typerefCustomDoubleAssociationKeyResource", Message.class, new ResourceSpecImpl(EnumSet.of(ResourceMethod.GET), new HashMap<String, DynamicRecordMetadata>(), new HashMap<String, DynamicRecordMetadata>(), CompoundKey.class, null, null, Message.class, keyParts), requestOptions);
    final String[] stringArray = { "foo" };
    GetRequest<Message> req = getBuilder.id(new CompoundKey().append("src", 100.0).append("dest", 200.0)).setReqParam("array", stringArray).build();
    Response<Message> resp = REST_CLIENT.sendRequest(req).getResponse();
    Message result = resp.getEntity();
    Assert.assertEquals(result.getId(), "100.0->200.0");
    Assert.assertEquals(result.getMessage(), String.format("I need some $20. Array contents %s.", Arrays.asList(stringArray)));
}
Also used : Message(com.linkedin.restli.examples.greetings.api.Message) HashMap(java.util.HashMap) CompoundKey(com.linkedin.restli.common.CompoundKey) ResourceSpecImpl(com.linkedin.restli.common.ResourceSpecImpl) GetRequestBuilder(com.linkedin.restli.client.GetRequestBuilder) Test(org.testng.annotations.Test)

Example 17 with CompoundKey

use of com.linkedin.restli.common.CompoundKey in project rest.li by linkedin.

the class RestLiRouter method parseCompoundKey.

private static CompoundKey parseCompoundKey(final ResourceModel resource, final ServerResourceContext context, final String pathSegment) {
    CompoundKey compoundKey;
    try {
        compoundKey = ArgumentUtils.parseCompoundKey(pathSegment, resource.getKeys(), context.getRestliProtocolVersion());
    } catch (PathSegmentSyntaxException e) {
        throw new RoutingException(String.format("input %s is not a Compound key", pathSegment), HttpStatus.S_400_BAD_REQUEST.getCode(), e);
    } catch (IllegalArgumentException e) {
        throw new RoutingException(String.format("input %s is not a Compound key", pathSegment), HttpStatus.S_400_BAD_REQUEST.getCode(), e);
    } catch (TemplateRuntimeException e) {
        // thrown from DateTemplateUtil.coerceOutput
        throw new RoutingException(String.format("Compound key parameter value %s is invalid", pathSegment), HttpStatus.S_400_BAD_REQUEST.getCode(), e);
    }
    for (String simpleKeyName : compoundKey.getPartKeys()) {
        context.getPathKeys().append(simpleKeyName, compoundKey.getPart(simpleKeyName));
    }
    context.getPathKeys().append(resource.getKeyName(), compoundKey);
    return compoundKey;
}
Also used : RoutingException(com.linkedin.restli.server.RoutingException) PathSegmentSyntaxException(com.linkedin.restli.internal.common.PathSegment.PathSegmentSyntaxException) CompoundKey(com.linkedin.restli.common.CompoundKey) TemplateRuntimeException(com.linkedin.data.template.TemplateRuntimeException)

Example 18 with CompoundKey

use of com.linkedin.restli.common.CompoundKey in project rest.li by linkedin.

the class RestLiRouter method parseBatchKeysParameter.

private void parseBatchKeysParameter(final ResourceModel resource, final ServerResourceContext context) {
    Class<?> keyClass = resource.getKeyClass();
    ProtocolVersion version = context.getRestliProtocolVersion();
    final Set<Object> batchKeys;
    try {
        if (context.getParameters().containsKey(RestConstants.ALT_KEY_PARAM)) {
            batchKeys = parseAlternativeBatchKeys(resource, context);
        } else if (ComplexResourceKey.class.equals(keyClass)) {
            // Parse all query parameters into a data map.
            DataMap allParametersDataMap = context.getParameters();
            // Get the batch request keys from the IDS list at the root of the map.
            DataList batchIds = allParametersDataMap.getDataList(RestConstants.QUERY_BATCH_IDS_PARAM);
            if (batchIds == null) {
                batchKeys = null;
            } else if (batchIds.isEmpty()) {
                batchKeys = Collections.emptySet();
            } else {
                batchKeys = new HashSet<Object>();
                // Validate the complex keys and put them into the context batch keys
                for (Object complexKey : batchIds) {
                    if (!(complexKey instanceof DataMap)) {
                        log.warn("Invalid structure of key '" + complexKey.toString() + "', skipping key.");
                        context.getBatchKeyErrors().put(complexKey, new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST));
                        continue;
                    }
                    batchKeys.add(ComplexResourceKey.buildFromDataMap((DataMap) complexKey, ComplexKeySpec.forClassesMaybeNull(resource.getKeyKeyClass(), resource.getKeyParamsClass())));
                }
            }
        } else if (CompoundKey.class.equals(keyClass) && version.compareTo(AllProtocolVersions.RESTLI_PROTOCOL_2_0_0.getProtocolVersion()) >= 0) {
            DataMap allParametersDataMap = context.getParameters();
            // Get the batch request keys from the IDS list at the root of the map.
            DataList batchIds = allParametersDataMap.getDataList(RestConstants.QUERY_BATCH_IDS_PARAM);
            if (batchIds == null) {
                batchKeys = null;
            } else if (batchIds.isEmpty()) {
                batchKeys = Collections.emptySet();
            } else {
                batchKeys = new HashSet<Object>();
                // Validate the compound keys and put them into the contex batch keys
                for (Object compoundKey : batchIds) {
                    if (!(compoundKey instanceof DataMap)) {
                        log.warn("Invalid structure of key '" + compoundKey.toString() + "', skipping key.");
                        context.getBatchKeyErrors().put(compoundKey.toString(), new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST));
                        continue;
                    }
                    CompoundKey finalKey;
                    try {
                        finalKey = ArgumentUtils.dataMapToCompoundKey((DataMap) compoundKey, resource.getKeys());
                    } catch (IllegalArgumentException e) {
                        log.warn("Invalid structure of key '" + compoundKey.toString() + "', skipping key.");
                        context.getBatchKeyErrors().put(compoundKey.toString(), new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST));
                        continue;
                    }
                    batchKeys.add(finalKey);
                }
            }
        } else // collection batch get in v2, collection or association batch get in v1
        if (context.hasParameter(RestConstants.QUERY_BATCH_IDS_PARAM)) {
            batchKeys = new HashSet<Object>();
            List<String> ids = context.getParameterValues(RestConstants.QUERY_BATCH_IDS_PARAM);
            if (version.compareTo(AllProtocolVersions.RESTLI_PROTOCOL_2_0_0.getProtocolVersion()) >= 0) {
                for (String id : ids) {
                    Key key = resource.getPrimaryKey();
                    Object value;
                    try {
                        // in v2, compound keys have already been converted and dealt with, so all we need to do here is convert simple values.
                        value = ArgumentUtils.convertSimpleValue(id, key.getDataSchema(), key.getType());
                        batchKeys.add(value);
                    } catch (NumberFormatException e) {
                        throw new RoutingException("NumberFormatException parsing batch key '" + id + "'", HttpStatus.S_400_BAD_REQUEST.getCode(), e);
                    } catch (IllegalArgumentException e) {
                        throw new RoutingException("IllegalArgumentException parsing batch key '" + id + "'", HttpStatus.S_400_BAD_REQUEST.getCode(), e);
                    }
                }
            } else {
                for (String id : ids) {
                    try {
                        // in v1, compound keys have not been fully parsed or dealt with yet, so we need to take them into account.
                        Object value = parseKeyFromBatchV1(id, resource);
                        batchKeys.add(value);
                    } catch (NumberFormatException e) {
                        log.warn("Caught NumberFormatException parsing batch key '" + id + "', skipping key.");
                        context.getBatchKeyErrors().put(id, new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST, null, e));
                    } catch (IllegalArgumentException e) {
                        log.warn("Caught IllegalArgumentException parsing batch key '" + id + "', skipping key.");
                        context.getBatchKeyErrors().put(id, new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST, null, e));
                    } catch (PathSegmentSyntaxException e) {
                        log.warn("Caught IllegalArgumentException parsing batch key '" + id + "', skipping key.");
                        context.getBatchKeyErrors().put(id, new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST, null, e));
                    }
                }
            }
        } else {
            batchKeys = null;
        }
    } catch (TemplateRuntimeException e) {
        // thrown from DateTemplateUtil.coerceOutput
        throw new RoutingException("Batch key parameter value is invalid", HttpStatus.S_400_BAD_REQUEST.getCode(), e);
    }
    context.getPathKeys().setBatchKeys(batchKeys);
}
Also used : RoutingException(com.linkedin.restli.server.RoutingException) CompoundKey(com.linkedin.restli.common.CompoundKey) ProtocolVersion(com.linkedin.restli.common.ProtocolVersion) DataMap(com.linkedin.data.DataMap) DataList(com.linkedin.data.DataList) PathSegmentSyntaxException(com.linkedin.restli.internal.common.PathSegment.PathSegmentSyntaxException) RestLiServiceException(com.linkedin.restli.server.RestLiServiceException) ComplexResourceKey(com.linkedin.restli.common.ComplexResourceKey) TemplateRuntimeException(com.linkedin.data.template.TemplateRuntimeException) LinkedList(java.util.LinkedList) DataList(com.linkedin.data.DataList) List(java.util.List) ComplexResourceKey(com.linkedin.restli.common.ComplexResourceKey) Key(com.linkedin.restli.server.Key) CompoundKey(com.linkedin.restli.common.CompoundKey) HashSet(java.util.HashSet)

Example 19 with CompoundKey

use of com.linkedin.restli.common.CompoundKey in project rest.li by linkedin.

the class TestBatchGetResponseBuilder method testAlternativeKeyBuilder.

@Test
public void testAlternativeKeyBuilder() {
    Map<CompoundKey, Foo> rawResults = new HashMap<CompoundKey, Foo>();
    CompoundKey c1 = new CompoundKey().append("a", "a1").append("b", 1);
    CompoundKey c2 = new CompoundKey().append("a", "a2").append("b", 2);
    Foo record1 = new Foo().setStringField("record1").setFruitsField(Fruits.APPLE);
    Foo record2 = new Foo().setStringField("record2").setIntField(7);
    rawResults.put(c1, record1);
    rawResults.put(c2, record2);
    Map<String, AlternativeKey<?, ?>> alternativeKeyMap = new HashMap<String, AlternativeKey<?, ?>>();
    alternativeKeyMap.put("alt", new AlternativeKey<String, CompoundKey>(new TestKeyCoercer(), String.class, new StringDataSchema()));
    Map<String, String> headers = ResponseBuilderUtil.getHeaders();
    ResourceContext mockContext = getMockResourceContext(AllProtocolVersions.LATEST_PROTOCOL_VERSION, Collections.<Object, RestLiServiceException>emptyMap(), "alt", null, null);
    ResourceMethodDescriptor mockDescriptor = getMockResourceMethodDescriptor(alternativeKeyMap);
    RoutingResult routingResult = new RoutingResult(mockContext, mockDescriptor);
    BatchGetResponseBuilder batchGetResponseBuilder = new BatchGetResponseBuilder(null);
    RestLiResponseData responseData = batchGetResponseBuilder.buildRestLiResponseData(null, routingResult, rawResults, headers, Collections.<HttpCookie>emptyList());
    PartialRestResponse restResponse = batchGetResponseBuilder.buildResponse(routingResult, responseData);
    EasyMock.verify(mockContext, mockDescriptor);
    ResponseBuilderUtil.validateHeaders(restResponse, headers);
    Assert.assertEquals(restResponse.getStatus(), HttpStatus.S_200_OK);
    @SuppressWarnings("unchecked") Map<String, Foo> results = ((BatchResponse<Foo>) restResponse.getEntity()).getResults();
    Assert.assertEquals(results.size(), 2);
    Assert.assertTrue(results.containsKey("aa1xb1"));
    Assert.assertTrue(results.containsKey("aa2xb2"));
}
Also used : ResourceContext(com.linkedin.restli.server.ResourceContext) ServerResourceContext(com.linkedin.restli.internal.server.ServerResourceContext) HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) CompoundKey(com.linkedin.restli.common.CompoundKey) BatchResponse(com.linkedin.restli.common.BatchResponse) Foo(com.linkedin.pegasus.generator.examples.Foo) ResourceMethodDescriptor(com.linkedin.restli.internal.server.model.ResourceMethodDescriptor) RestLiResponseData(com.linkedin.restli.server.RestLiResponseData) StringDataSchema(com.linkedin.data.schema.StringDataSchema) RoutingResult(com.linkedin.restli.internal.server.RoutingResult) AlternativeKey(com.linkedin.restli.server.AlternativeKey) Test(org.testng.annotations.Test)

Example 20 with CompoundKey

use of com.linkedin.restli.common.CompoundKey in project rest.li by linkedin.

the class TestBatchPatchArgumentBuilder method failureData.

@DataProvider
private Object[][] failureData() {
    Object[] compoundKeys = new Object[] { new CompoundKey().append("string1", "apples").append("string2", "oranges"), new CompoundKey().append("string1", "XYZ").append("string2", "tea") };
    Object[] complexResourceKeys = new Object[] { new ComplexResourceKey<MyComplexKey, EmptyRecord>(new MyComplexKey().setA("XYZ").setB(111L), new EmptyRecord()), new ComplexResourceKey<MyComplexKey, EmptyRecord>(new MyComplexKey().setA("A2").setB(222L), new EmptyRecord()) };
    return new Object[][] { { AllProtocolVersions.RESTLI_PROTOCOL_1_0_0.getProtocolVersion(), new Key("integerKey", Integer.class, new IntegerDataSchema()), null, "{\"entities\":{\"10001\":{\"patch\":{\"$set\":{\"a\":\"someString\"}}}," + "\"10002\":{\"patch\":{\"$set\":{\"a\":\"someOtherString\"}}}}}", new Object[] { 10001, 99999 }, ERROR_MESSAGE_BATCH_KEYS_MISMATCH }, { AllProtocolVersions.RESTLI_PROTOCOL_1_0_0.getProtocolVersion(), new Key("integerKey", Integer.class, new IntegerDataSchema()), null, "{\"entities\":{\"10001\":{\"patch\":{\"$set\":{\"a\":\"someString\"}}}," + "\"99999\":{\"patch\":{\"$set\":{\"a\":\"someOtherString\"}}}}}", new Object[] { 10001, 10002 }, ERROR_MESSAGE_BATCH_KEYS_MISMATCH }, { AllProtocolVersions.RESTLI_PROTOCOL_1_0_0.getProtocolVersion(), new Key("integerKey", Integer.class, new IntegerDataSchema()), null, "{\"entities\":{\"10001\":{\"patch\":{\"$set\":{\"a\":\"someString\"}}}," + "\"10002\":{\"patch\":{\"$set\":{\"a\":\"someOtherString\"}}}}}", new Object[] { 10001, 10002, 10003 }, ERROR_MESSAGE_BATCH_KEYS_MISMATCH }, { AllProtocolVersions.RESTLI_PROTOCOL_1_0_0.getProtocolVersion(), new Key("compoundKey", CompoundKey.class, null), new Key[] { new Key("string1", String.class), new Key("string2", String.class) }, "{\"entities\":{\"string1=apples&string2=oranges\":{\"patch\":{\"$set\":{\"a\":\"someString\"}}}," + "\"string1=coffee&string2=tea\":{\"patch\":{\"$set\":{\"a\":\"someOtherString\"}}}}}", compoundKeys, ERROR_MESSAGE_BATCH_KEYS_MISMATCH }, { // Duplicate key in the entities body
    AllProtocolVersions.RESTLI_PROTOCOL_1_0_0.getProtocolVersion(), new Key("compoundKey", CompoundKey.class, null), new Key[] { new Key("string1", String.class), new Key("string2", String.class) }, "{\"entities\":{\"string1=apples&string2=oranges\":{\"patch\":{\"$set\":{\"a\":\"someString\"}}}," + "\"string2=oranges&string1=apples\":{\"patch\":{\"$set\":{\"a\":\"someOtherString\"}}}}}", compoundKeys, ERROR_MESSAGE_DUPLICATE_BATCH_KEYS }, { AllProtocolVersions.RESTLI_PROTOCOL_2_0_0.getProtocolVersion(), new Key("compoundKey", CompoundKey.class, null), new Key[] { new Key("string1", String.class), new Key("string2", String.class) }, "{\"entities\":{\"(string1:apples,string2:oranges)\":{\"patch\":{\"$set\":{\"a\":\"someString\"}}}," + "\"(string1:coffee,string2:tea)\":{\"patch\":{\"$set\":{\"a\":\"someOtherString\"}}}}}", compoundKeys, ERROR_MESSAGE_BATCH_KEYS_MISMATCH }, { // Duplicate key in the entities body
    AllProtocolVersions.RESTLI_PROTOCOL_2_0_0.getProtocolVersion(), new Key("compoundKey", CompoundKey.class, null), new Key[] { new Key("string1", String.class), new Key("string2", String.class) }, "{\"entities\":{\"(string1:apples,string2:oranges)\":{\"patch\":{\"$set\":{\"a\":\"someString\"}}}," + "\"(string2:oranges,string1:apples)\":{\"patch\":{\"$set\":{\"a\":\"someOtherString\"}}}}}", compoundKeys, ERROR_MESSAGE_DUPLICATE_BATCH_KEYS }, { AllProtocolVersions.RESTLI_PROTOCOL_1_0_0.getProtocolVersion(), new Key("complexKey", ComplexResourceKey.class, null), null, "{\"entities\":{\"a=A1&b=111\":{\"patch\":{\"$set\":{\"a\":\"someString\"}}}," + "\"a=A2&b=222\":{\"patch\":{\"$set\":{\"a\":\"someOtherString\"}}}}}", complexResourceKeys, ERROR_MESSAGE_BATCH_KEYS_MISMATCH }, { // Duplicate key in the entities body
    AllProtocolVersions.RESTLI_PROTOCOL_1_0_0.getProtocolVersion(), new Key("complexKey", ComplexResourceKey.class, null), null, "{\"entities\":{\"a=A2&b=222\":{\"patch\":{\"$set\":{\"a\":\"someString\"}}}," + "\"b=222&a=A2\":{\"patch\":{\"$set\":{\"a\":\"someOtherString\"}}}}}", complexResourceKeys, ERROR_MESSAGE_DUPLICATE_BATCH_KEYS }, { AllProtocolVersions.RESTLI_PROTOCOL_2_0_0.getProtocolVersion(), new Key("complexKey", ComplexResourceKey.class, null), null, "{\"entities\":{\"($params:(),a:A2,b:222)\":{\"patch\":{\"$set\":{\"a\":\"someOtherString\"}}}," + "\"($params:(),a:A1,b:111)\":{\"patch\":{\"$set\":{\"a\":\"someString\"}}}}}", complexResourceKeys, ERROR_MESSAGE_BATCH_KEYS_MISMATCH }, { // Duplicate key in the entities body
    AllProtocolVersions.RESTLI_PROTOCOL_2_0_0.getProtocolVersion(), new Key("complexKey", ComplexResourceKey.class, null), null, "{\"entities\":{\"($params:(),a:A2,b:222)\":{\"patch\":{\"$set\":{\"a\":\"someOtherString\"}}}," + "\"($params:(),b:222,a:A2)\":{\"patch\":{\"$set\":{\"a\":\"someString\"}}}}}", complexResourceKeys, ERROR_MESSAGE_DUPLICATE_BATCH_KEYS } };
}
Also used : EmptyRecord(com.linkedin.restli.common.EmptyRecord) MyComplexKey(com.linkedin.restli.common.test.MyComplexKey) IntegerDataSchema(com.linkedin.data.schema.IntegerDataSchema) CompoundKey(com.linkedin.restli.common.CompoundKey) ComplexResourceKey(com.linkedin.restli.common.ComplexResourceKey) MyComplexKey(com.linkedin.restli.common.test.MyComplexKey) ComplexResourceKey(com.linkedin.restli.common.ComplexResourceKey) Key(com.linkedin.restli.server.Key) CompoundKey(com.linkedin.restli.common.CompoundKey) DataProvider(org.testng.annotations.DataProvider)

Aggregations

CompoundKey (com.linkedin.restli.common.CompoundKey)94 Test (org.testng.annotations.Test)48 HashMap (java.util.HashMap)26 DataProvider (org.testng.annotations.DataProvider)20 ComplexResourceKey (com.linkedin.restli.common.ComplexResourceKey)17 ResourceMethodDescriptor (com.linkedin.restli.internal.server.model.ResourceMethodDescriptor)16 GroupMembership (com.linkedin.restli.examples.groups.api.GroupMembership)15 ResourceModel (com.linkedin.restli.internal.server.model.ResourceModel)14 AfterTest (org.testng.annotations.AfterTest)13 BeforeTest (org.testng.annotations.BeforeTest)13 DataMap (com.linkedin.data.DataMap)12 RestLiTestHelper.buildResourceModel (com.linkedin.restli.server.test.RestLiTestHelper.buildResourceModel)12 Key (com.linkedin.restli.server.Key)11 Followed (com.linkedin.restli.server.twitter.TwitterTestDataModels.Followed)10 HashSet (java.util.HashSet)10 BatchKVResponse (com.linkedin.restli.client.response.BatchKVResponse)9 TestRecord (com.linkedin.restli.client.test.TestRecord)9 BatchUpdateResult (com.linkedin.restli.server.BatchUpdateResult)9 AsyncFollowsAssociativeResource (com.linkedin.restli.server.twitter.AsyncFollowsAssociativeResource)9 EmptyRecord (com.linkedin.restli.common.EmptyRecord)8