use of com.linkedin.restli.common.CompoundKey in project rest.li by linkedin.
the class GroupMembershipsResource3 method complexKeyToCompoundKey.
private static CompoundKey complexKeyToCompoundKey(ComplexResourceKey<GroupMembershipKey, GroupMembershipParam> id) {
GroupMembershipKey key = id.getKey();
CompoundKey compoundKey = new CompoundKey();
compoundKey.append(GROUP_ID, key.getGroupID(GetMode.NULL));
compoundKey.append(MEMBER_ID, key.getMemberID(GetMode.NULL));
return compoundKey;
}
use of com.linkedin.restli.common.CompoundKey in project rest.li by linkedin.
the class TestGroupsClient method buildCompoundKey.
private static CompoundKey buildCompoundKey(int memberID, int groupID) {
CompoundKey compoundKey = new CompoundKey();
compoundKey.append("memberID", memberID);
compoundKey.append("groupID", groupID);
return compoundKey;
}
use of com.linkedin.restli.common.CompoundKey in project rest.li by linkedin.
the class ArgumentUtils method parseCompoundKey.
/**
* The method parses out runtime-typesafe simple keys for the compound key based on the
* provided key set for the resource.
*
*
* @param urlString a string representation of the compound key.
* @param keys a set of {@link com.linkedin.restli.server.Key} objects specifying
* names and types of the constituent simple keys
* @return a runtime-typesafe CompoundKey
* @throws IllegalArgumentException if there are unexpected key parts in the urlString that are not in keys,
* or any error in {@link ProtocolVersion} 1.0
* @throws PathSegmentSyntaxException if the given string is not a valid encoded compound key
*/
public static CompoundKey parseCompoundKey(final String urlString, final Collection<Key> keys, final ProtocolVersion version) throws IllegalArgumentException, PathSegmentSyntaxException {
if (urlString == null || urlString.trim().isEmpty()) {
return null;
}
if (version.compareTo(AllProtocolVersions.RESTLI_PROTOCOL_2_0_0.getProtocolVersion()) >= 0) {
return parseCompoundKeyV2(urlString, keys);
} else {
//There are two compound key syntaxes potentially in use by clients, depending on the version
//of rest.li being used. The syntaxes use different delimiters: ";" and ":" for the legacy
//syntax, and "&" and "=" for the newer syntax. When parsing compound keys, we do not
//know which syntax the client used, and we cannot rely on correct percent-encoding of
//delimiter characters for both syntaxes. Therefore we simulate parsing using each syntax in
//turn, and choose the best match.
StringBuilder legacyParseError = new StringBuilder();
StringBuilder currentParseError = new StringBuilder();
CompoundKey legacyParsedKey = parseCompoundKey(urlString, keys, legacyParseError, LEGACY_SIMPLE_KEY_DELIMETER_PATTERN, LEGACY_KEY_VALUE_DELIMETER_PATTERN);
CompoundKey currentParsedKey = parseCompoundKey(urlString, keys, currentParseError, SIMPLE_KEY_DELIMETER_PATTERN, KEY_VALUE_DELIMETER_PATTERN);
if (legacyParsedKey != null && currentParsedKey != null) {
boolean legacy = legacyParsedKey.getNumParts() > currentParsedKey.getNumParts();
_log.warn("Ambiguous compound key syntax, using heuristic decision for '{}', legacy: {}", urlString, String.valueOf(legacy));
return legacy ? legacyParsedKey : currentParsedKey;
} else if (legacyParsedKey == null && currentParsedKey == null) {
throw new IllegalArgumentException(currentParseError.toString());
} else {
return currentParsedKey == null ? legacyParsedKey : currentParsedKey;
}
}
}
use of com.linkedin.restli.common.CompoundKey in project rest.li by linkedin.
the class ArgumentUtils method parseCompoundKey.
/**
* Parse {@link CompoundKey} from its String representation.
*
* @param urlString {@link CompoundKey} string representation
* @param keys {@link CompoundKey} constituent keys' classes keyed on their names
* @param errorMessageBuilder {@link StringBuilder} to build error message if necessary
* @param simpleKeyDelimiterPattern delimiter of constituent keys in the compound key
* @param keyValueDelimiterPattern delimiter of key and value in a constituent key
* @return {@link CompoundKey} parsed from the input string
*/
public static CompoundKey parseCompoundKey(final String urlString, final Collection<Key> keys, final StringBuilder errorMessageBuilder, final Pattern simpleKeyDelimiterPattern, final Pattern keyValueDelimiterPattern) throws RoutingException {
String[] simpleKeys = simpleKeyDelimiterPattern.split(urlString.trim());
CompoundKey compoundKey = new CompoundKey();
for (String simpleKey : simpleKeys) {
String[] nameValuePair = keyValueDelimiterPattern.split(simpleKey.trim());
if (simpleKey.trim().length() == 0 || nameValuePair.length != 2) {
errorMessageBuilder.append("Bad key format '");
errorMessageBuilder.append(urlString);
errorMessageBuilder.append("'");
return null;
}
// Simple key names and values are URL-encoded prior to being included in the URL on
// the client, to prevent collision with any of the delimiter characters (bulk,
// compound key and simple key-value). So, must decode them
String name;
try {
name = URLDecoder.decode(nameValuePair[0], RestConstants.DEFAULT_CHARSET_NAME);
} catch (UnsupportedEncodingException e) {
//should not happen, since we are using "UTF-8" as the encoding
throw new RestLiInternalException(e);
}
// Key is not found in the set defined for the resource
Key currentKey = getKeyWithName(keys, name);
if (currentKey == null) {
errorMessageBuilder.append("Unknown key part named '");
errorMessageBuilder.append(name);
errorMessageBuilder.append("'");
return null;
}
String decodedStringValue;
try {
decodedStringValue = URLDecoder.decode(nameValuePair[1], RestConstants.DEFAULT_CHARSET_NAME);
} catch (UnsupportedEncodingException e) {
//should not happen, since we are using "UTF-8" as the encoding
throw new RestLiInternalException(e);
}
compoundKey.append(name, convertSimpleValue(decodedStringValue, currentKey.getDataSchema(), currentKey.getType()));
}
return compoundKey;
}
use of com.linkedin.restli.common.CompoundKey in project rest.li by linkedin.
the class TestRestLiMethodInvocation method testAsyncPut.
@SuppressWarnings("unchecked")
@Test
public void testAsyncPut() throws Exception {
Map<String, ResourceModel> resourceModelMap = buildResourceModels(AsyncStatusCollectionResource.class, AsyncLocationResource.class, AsyncDiscoveredItemsResource.class);
ResourceModel statusResourceModel = resourceModelMap.get("/asyncstatuses");
ResourceModel locationResourceModel = statusResourceModel.getSubResource("asynclocation");
ResourceModel followsAssociationResourceModel = buildResourceModel(AsyncFollowsAssociativeResource.class);
ResourceModel discoveredItemsResourceModel = resourceModelMap.get("/asyncdiscovereditems");
RestLiCallback<?> callback = getCallback();
ResourceMethodDescriptor methodDescriptor;
AsyncStatusCollectionResource statusResource;
AsyncFollowsAssociativeResource followsResource;
AsyncLocationResource locationResource;
AsyncDiscoveredItemsResource discoveredItemsResource;
// #1 Update on collection resource
methodDescriptor = statusResourceModel.findMethod(ResourceMethod.UPDATE);
statusResource = getMockResource(AsyncStatusCollectionResource.class);
long id = eq(1L);
Status status = (Status) EasyMock.anyObject();
statusResource.update(id, status, EasyMock.<Callback<UpdateResponse>>anyObject());
EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
@Override
public Object answer() throws Throwable {
@SuppressWarnings("unchecked") Callback<UpdateResponse> callback = (Callback<UpdateResponse>) EasyMock.getCurrentArguments()[2];
callback.onSuccess(null);
return null;
}
});
EasyMock.replay(statusResource);
checkAsyncInvocation(statusResource, callback, methodDescriptor, "PUT", version, "/asyncstatuses/1", "{}", buildPathKeys("statusID", 1L));
// #2 Update on association resource
methodDescriptor = followsAssociationResourceModel.findMethod(ResourceMethod.UPDATE);
followsResource = getMockResource(AsyncFollowsAssociativeResource.class);
CompoundKey rawKey = new CompoundKey();
rawKey.append("followerID", 1L);
rawKey.append("followeeID", 2L);
CompoundKey key = eq(rawKey);
Followed followed = (Followed) EasyMock.anyObject();
followsResource.update(key, followed, (Callback<UpdateResponse>) EasyMock.anyObject());
EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
@Override
public Object answer() throws Throwable {
Callback<UpdateResponse> callback = (Callback<UpdateResponse>) EasyMock.getCurrentArguments()[2];
callback.onSuccess(null);
return null;
}
});
EasyMock.replay(followsResource);
checkAsyncInvocation(followsResource, callback, methodDescriptor, "PUT", version, "/asyncfollows/(followerID:1,followeeID:2)", "{}", buildPathKeys("followerID", 1L, "followeeID", 2L, followsAssociationResourceModel.getKeyName(), rawKey));
// #3 Update on simple resource
methodDescriptor = locationResourceModel.findMethod(ResourceMethod.UPDATE);
locationResource = getMockResource(AsyncLocationResource.class);
Location location = (Location) EasyMock.anyObject();
locationResource.update(location, EasyMock.<Callback<UpdateResponse>>anyObject());
EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
@Override
public Object answer() throws Throwable {
@SuppressWarnings("unchecked") Callback<UpdateResponse> callback = (Callback<UpdateResponse>) EasyMock.getCurrentArguments()[1];
callback.onSuccess(null);
return null;
}
});
EasyMock.replay(locationResource);
checkAsyncInvocation(locationResource, callback, methodDescriptor, "PUT", version, "/asyncstatuses/1/asynclocation", "{}", buildPathKeys("statusID", 1L));
// #4 Update on complex-key resource
methodDescriptor = discoveredItemsResourceModel.findMethod(ResourceMethod.UPDATE);
discoveredItemsResource = getMockResource(AsyncDiscoveredItemsResource.class);
ComplexResourceKey<DiscoveredItemKey, DiscoveredItemKeyParams> complexKey = getDiscoveredItemComplexKey(1L, 2, 3L);
discoveredItemsResource.update(eq(complexKey), (DiscoveredItem) EasyMock.anyObject(), EasyMock.<Callback<UpdateResponse>>anyObject());
EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
@Override
public Object answer() throws Throwable {
@SuppressWarnings("unchecked") Callback<UpdateResponse> callback = (Callback<UpdateResponse>) EasyMock.getCurrentArguments()[2];
callback.onSuccess(null);
return null;
}
});
EasyMock.replay(discoveredItemsResource);
checkAsyncInvocation(discoveredItemsResource, callback, methodDescriptor, "PUT", version, "/asyncdiscovereditems/(itemId:1,type:2,userId:3)", "{}", buildPathKeys("asyncDiscoveredItemId", complexKey));
}
Aggregations