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);
}
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());
}
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);
}
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 } };
}
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 } };
}
Aggregations