Search in sources :

Example 6 with Key

use of com.linkedin.restli.server.Key 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 7 with Key

use of com.linkedin.restli.server.Key in project rest.li by linkedin.

the class ResourceModelEncoder method appendKeys.

private void appendKeys(final AssociationSchema associationSchema, final ResourceModel collectionModel) {
    AssocKeySchemaArray assocKeySchemaArray = new AssocKeySchemaArray();
    List<Key> sortedKeys = new ArrayList<Key>(collectionModel.getKeys());
    Collections.sort(sortedKeys, new Comparator<Key>() {

        @Override
        public int compare(final Key o1, final Key o2) {
            return o1.getName().compareTo(o2.getName());
        }
    });
    for (Key key : sortedKeys) {
        AssocKeySchema assocKeySchema = new AssocKeySchema();
        assocKeySchema.setName(key.getName());
        assocKeySchema.setType(buildDataSchemaType(key.getType(), key.getDataSchema()));
        assocKeySchemaArray.add(assocKeySchema);
    }
    associationSchema.setAssocKeys(assocKeySchemaArray);
    associationSchema.setIdentifier(collectionModel.getKeyName());
}
Also used : AssocKeySchemaArray(com.linkedin.restli.restspec.AssocKeySchemaArray) ArrayList(java.util.ArrayList) ComplexResourceKey(com.linkedin.restli.common.ComplexResourceKey) Key(com.linkedin.restli.server.Key) AlternativeKey(com.linkedin.restli.server.AlternativeKey) AssocKeySchema(com.linkedin.restli.restspec.AssocKeySchema)

Example 8 with Key

use of com.linkedin.restli.server.Key in project rest.li by linkedin.

the class ResourceModelEncoder method appendIdentifierNode.

private void appendIdentifierNode(final CollectionSchema collectionNode, final ResourceModel collectionResource) {
    IdentifierSchema identifierSchema = new IdentifierSchema();
    identifierSchema.setName(collectionResource.getKeyName());
    // Otherwise, just set the type to the key class schema type
    if (collectionResource.getKeyClass().equals(ComplexResourceKey.class)) {
        identifierSchema.setType(buildDataSchemaType(collectionResource.getKeyKeyClass()));
        identifierSchema.setParams(buildDataSchemaType(collectionResource.getKeyParamsClass()));
    } else {
        Key key = collectionResource.getPrimaryKey();
        identifierSchema.setType(buildDataSchemaType(key.getType(), key.getDataSchema()));
    }
    collectionNode.setIdentifier(identifierSchema);
}
Also used : IdentifierSchema(com.linkedin.restli.restspec.IdentifierSchema) ComplexResourceKey(com.linkedin.restli.common.ComplexResourceKey) Key(com.linkedin.restli.server.Key) AlternativeKey(com.linkedin.restli.server.AlternativeKey)

Example 9 with Key

use of com.linkedin.restli.server.Key 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)

Example 10 with Key

use of com.linkedin.restli.server.Key in project rest.li by linkedin.

the class TestBatchPatchArgumentBuilder method argumentData.

@DataProvider(name = "argumentData")
private Object[][] argumentData() {
    Map<String, Object> aMap1 = new HashMap<String, Object>();
    aMap1.put("a", "someString");
    Map<String, Object> setMap1 = new HashMap<String, Object>();
    setMap1.put("$set", new DataMap(aMap1));
    Map<String, Object> patchMap1 = new HashMap<String, Object>();
    patchMap1.put("patch", new DataMap(setMap1));
    PatchRequest<MyComplexKey> patch1 = new PatchRequest<MyComplexKey>(new DataMap(patchMap1));
    Map<String, Object> aMap2 = new HashMap<String, Object>();
    aMap2.put("a", "someOtherString");
    Map<String, Object> setMap2 = new HashMap<String, Object>();
    setMap2.put("$set", new DataMap(aMap2));
    Map<String, Object> data2 = new HashMap<String, Object>();
    data2.put("patch", new DataMap(setMap2));
    PatchRequest<MyComplexKey> patch2 = new PatchRequest<MyComplexKey>(new DataMap(data2));
    @SuppressWarnings("rawtypes") PatchRequest[] patches = new PatchRequest[] { patch1, patch2 };
    Object[] simpleKeys = new Object[] { "simple", "(s:pe%cial)" };
    Object[] compoundKeys = new Object[] { new CompoundKey().append("string1", "apples").append("string2", "oranges"), new CompoundKey().append("string1", "simple").append("string2", "(s:pe%cial)") };
    Object[] complexResourceKeys = new Object[] { new ComplexResourceKey<MyComplexKey, EmptyRecord>(new MyComplexKey().setA("simple").setB(111L), new EmptyRecord()), new ComplexResourceKey<MyComplexKey, EmptyRecord>(new MyComplexKey().setA("(s:pe%cial)").setB(222L), new EmptyRecord()) };
    return new Object[][] { { AllProtocolVersions.RESTLI_PROTOCOL_1_0_0.getProtocolVersion(), new Key("stringKey", String.class, new StringDataSchema()), null, "{\"entities\":{\"simple\":{\"patch\":{\"$set\":{\"a\":\"someString\"}}}," + "\"(s:pe%cial)\":{\"patch\":{\"$set\":{\"a\":\"someOtherString\"}}}}}", simpleKeys, patches }, { AllProtocolVersions.RESTLI_PROTOCOL_2_0_0.getProtocolVersion(), new Key("stringKey", String.class, new StringDataSchema()), null, "{\"entities\":{\"simple\":{\"patch\":{\"$set\":{\"a\":\"someString\"}}}," + "\"(s:pe%cial)\":{\"patch\":{\"$set\":{\"a\":\"someOtherString\"}}}}}", simpleKeys, patches }, { 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=simple&string2=(s:pe%25cial)\":{\"patch\":{\"$set\":{\"a\":\"someOtherString\"}}}}}", compoundKeys, patches }, { 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:simple,string2:%28s%3Ape%25cial%29)\":{\"patch\":{\"$set\":{\"a\":\"someOtherString\"}}}}}", compoundKeys, patches }, { AllProtocolVersions.RESTLI_PROTOCOL_1_0_0.getProtocolVersion(), new Key("complexKey", ComplexResourceKey.class, null), null, "{\"entities\":{\"a=simple&b=111\":{\"patch\":{\"$set\":{\"a\":\"someString\"}}}," + "\"a=(s:pe%25cial)&b=222\":{\"patch\":{\"$set\":{\"a\":\"someOtherString\"}}}}}", complexResourceKeys, patches }, { AllProtocolVersions.RESTLI_PROTOCOL_2_0_0.getProtocolVersion(), new Key("complexKey", ComplexResourceKey.class, null), null, "{\"entities\":{\"($params:(),a:%28s%3Ape%25cial%29,b:222)\":{\"patch\":{\"$set\":{\"a\":\"someOtherString\"}}}," + "\"($params:(),a:simple,b:111)\":{\"patch\":{\"$set\":{\"a\":\"someString\"}}}}}", complexResourceKeys, patches } };
}
Also used : EmptyRecord(com.linkedin.restli.common.EmptyRecord) MyComplexKey(com.linkedin.restli.common.test.MyComplexKey) HashMap(java.util.HashMap) CompoundKey(com.linkedin.restli.common.CompoundKey) PatchRequest(com.linkedin.restli.common.PatchRequest) BatchPatchRequest(com.linkedin.restli.server.BatchPatchRequest) DataMap(com.linkedin.data.DataMap) StringDataSchema(com.linkedin.data.schema.StringDataSchema) 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

ComplexResourceKey (com.linkedin.restli.common.ComplexResourceKey)22 Key (com.linkedin.restli.server.Key)22 CompoundKey (com.linkedin.restli.common.CompoundKey)18 MyComplexKey (com.linkedin.restli.common.test.MyComplexKey)10 IntegerDataSchema (com.linkedin.data.schema.IntegerDataSchema)7 DataProvider (org.testng.annotations.DataProvider)7 EmptyRecord (com.linkedin.restli.common.EmptyRecord)6 ResourceModel (com.linkedin.restli.internal.server.model.ResourceModel)6 Parameter (com.linkedin.restli.internal.server.model.Parameter)5 AlternativeKey (com.linkedin.restli.server.AlternativeKey)5 ResourceContext (com.linkedin.restli.server.ResourceContext)5 HashSet (java.util.HashSet)5 Test (org.testng.annotations.Test)5 RestRequest (com.linkedin.r2.message.rest.RestRequest)4 RoutingResult (com.linkedin.restli.internal.server.RoutingResult)4 ResourceMethodDescriptor (com.linkedin.restli.internal.server.model.ResourceMethodDescriptor)4 RestLiRequestData (com.linkedin.restli.server.RestLiRequestData)4 ArrayList (java.util.ArrayList)4 DataMap (com.linkedin.data.DataMap)3 AnnotationSet (com.linkedin.restli.internal.server.model.AnnotationSet)3