/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.apache.shindig.social.opensocial.service;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Future;
import org.apache.shindig.common.util.FutureUtil;
import org.apache.shindig.config.ContainerConfig;
import org.apache.shindig.protocol.HandlerPreconditions;
import org.apache.shindig.protocol.Operation;
import org.apache.shindig.protocol.ProtocolException;
import org.apache.shindig.protocol.RequestItem;
import org.apache.shindig.protocol.RestfulCollection;
import org.apache.shindig.protocol.Service;
import org.apache.shindig.social.opensocial.model.Person;
import org.apache.shindig.social.opensocial.spi.CollectionOptions;
import org.apache.shindig.social.opensocial.spi.GroupId;
import org.apache.shindig.social.opensocial.spi.PersonService;
import org.apache.shindig.social.opensocial.spi.UserId;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Inject;
/**
* RPC/REST handler for all /people requests
*/
@Service(name = "people", path = "/{userId}+/{groupId}/{personId}+")
public class PersonHandler {
private final PersonService personService;
private final ContainerConfig config;
@Inject
public PersonHandler(PersonService personService, ContainerConfig config) {
this.personService = personService;
this.config = config;
}
/**
* Allowed end-points /people/{userId}+/{groupId} /people/{userId}/{groupId}/{optionalPersonId}+
*
* examples: /people/john.doe/@all /people/john.doe/@friends /people/john.doe/@self
*/
@Operation(httpMethods = "GET")
public Future<?> get(SocialRequestItem request) throws ProtocolException {
GroupId groupId = request.getGroup();
Set<String> optionalPersonId = ImmutableSet.copyOf(request.getListParameter("personId"));
Set<String> fields = request.getFields(Person.Field.DEFAULT_FIELDS);
Set<UserId> userIds = request.getUsers();
// Preconditions
HandlerPreconditions.requireNotEmpty(userIds, "No userId specified");
if (userIds.size() > 1 && !optionalPersonId.isEmpty()) {
throw new IllegalArgumentException("Cannot fetch personIds for multiple userIds");
}
CollectionOptions options = new CollectionOptions(request);
if (userIds.size() == 1) {
if (optionalPersonId.isEmpty()) {
if (groupId.getType() == GroupId.Type.self) {
// If a filter is set then we have to call getPeople(), otherwise use the simpler getPerson()
if (options.getFilter() != null) {
Future<RestfulCollection<Person>> people = personService.getPeople(
userIds, groupId, options, fields, request.getToken());
return FutureUtil.getFirstFromCollection(people);
} else {
return personService.getPerson(userIds.iterator().next(), fields, request.getToken());
}
} else {
return personService.getPeople(userIds, groupId, options, fields, request.getToken());
}
} else if (optionalPersonId.size() == 1) {
// TODO: Add some crazy concept to handle the userId?
Set<UserId> optionalUserIds = ImmutableSet.of(
new UserId(UserId.Type.userId, optionalPersonId.iterator().next()));
Future<RestfulCollection<Person>> people = personService.getPeople(
optionalUserIds, new GroupId(GroupId.Type.self, null),
options, fields, request.getToken());
return FutureUtil.getFirstFromCollection(people);
} else {
ImmutableSet.Builder<UserId> personIds = ImmutableSet.builder();
for (String pid : optionalPersonId) {
personIds.add(new UserId(UserId.Type.userId, pid));
}
// Every other case is a collection response of optional person ids
return personService.getPeople(personIds.build(), new GroupId(GroupId.Type.self, null),
options, fields, request.getToken());
}
}
// Every other case is a collection response.
return personService.getPeople(userIds, groupId, options, fields, request.getToken());
}
@Operation(httpMethods = "GET", path="/@supportedFields")
public List<Object> supportedFields(RequestItem request) {
// TODO: Would be nice if name in config matched name of service.
String container = Objects.firstNonNull(request.getToken().getContainer(), "default");
return config.getList(container,
"${Cur['gadgets.features'].opensocial.supportedFields.person}");
}
}