/*
* 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 com.google.common.base.Objects;
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.Service;
import org.apache.shindig.social.opensocial.model.Album;
import org.apache.shindig.social.opensocial.spi.AlbumService;
import org.apache.shindig.social.opensocial.spi.CollectionOptions;
import org.apache.shindig.social.opensocial.spi.UserId;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.inject.Inject;
/**
* Receives and delegates requests to the OpenSocial Album service.
*
* @since 2.0.0
*/
@Service(name = "albums", path = "/{userId}+/{groupId}/{albumId}+")
public class AlbumHandler {
private final AlbumService service;
private final ContainerConfig config;
@Inject
public AlbumHandler(AlbumService service, ContainerConfig config) {
this.service = service;
this.config = config;
}
/*
* Handles create operations.
*
* Allowed end-points: /albums/{userId}/@self
*
* Examples: /albums/john.doe/@self
*/
@Operation(httpMethods = "POST", bodyParam = "album")
public Future<?> create(SocialRequestItem request) throws ProtocolException {
// Retrieve userIds and albumIds
Set<UserId> userIds = request.getUsers();
List<String> albumIds = request.getListParameter("albumId");
// Preconditions - exactly one userId specified, no albumIds specified
HandlerPreconditions.requireNotEmpty(userIds, "No userId specified");
HandlerPreconditions.requireSingular(userIds, "Multiple userIds not supported");
HandlerPreconditions.requireEmpty(albumIds, "Cannot specify albumId in create");
return service.createAlbum(Iterables.getOnlyElement(userIds),
request.getAppId(),
request.getTypedParameter("album", Album.class),
request.getToken());
}
/*
* Handles retrieve operations.
*
* Allowed end-points: /albums/{userId}+/{groupId}/{albumId}+
*
* Examples: /albums/@me/@self /albums/john.doe/@self/1,2
* /albums/john.doe,jane.doe/@friends
*/
@Operation(httpMethods = "GET")
public Future<?> get(SocialRequestItem request) throws ProtocolException {
// Get user, group, and album IDs
Set<UserId> userIds = request.getUsers();
Set<String> optionalAlbumIds = ImmutableSet.copyOf(request
.getListParameter("albumId"));
// At least one userId must be specified
HandlerPreconditions.requireNotEmpty(userIds, "No userId specified");
// If multiple userIds specified, albumIds must not be specified
if (userIds.size() > 1 && !optionalAlbumIds.isEmpty()) {
throw new IllegalArgumentException("Cannot fetch same albumIds for multiple userIds");
}
// Retrieve albums by ID
if (!optionalAlbumIds.isEmpty()) {
if (optionalAlbumIds.size() == 1) {
return service.getAlbum(Iterables.getOnlyElement(userIds),
request.getAppId(), request.getFields(),
optionalAlbumIds.iterator().next(), request.getToken());
} else {
return service.getAlbums(Iterables.getOnlyElement(userIds),
request.getAppId(), request.getFields(),
new CollectionOptions(request), optionalAlbumIds,
request.getToken());
}
}
// Retrieve albums by group
return service.getAlbums(userIds, request.getGroup(), request
.getAppId(), request.getFields(),
new CollectionOptions(request), request.getToken());
}
/*
* Handles update operations.
*
* Allowed end-points: /albums/{userId}/@self/{albumId}
*
* Examples: /albums/john.doe/@self/1
*/
@Operation(httpMethods = "PUT", bodyParam = "album")
public Future<?> update(SocialRequestItem request) throws ProtocolException {
// Retrieve userIds and albumIds
Set<UserId> userIds = request.getUsers();
List<String> albumIds = request.getListParameter("albumId");
// Enforce preconditions - exactly one user and one album specified
HandlerPreconditions.requireNotEmpty(userIds, "No userId specified");
HandlerPreconditions.requireSingular(userIds, "Multiple userIds not supported");
HandlerPreconditions.requireNotEmpty(albumIds, "No albumId specified");
HandlerPreconditions.requireSingular(albumIds, "Multiple albumIds not supported");
return service.updateAlbum(Iterables.getOnlyElement(userIds),
request.getAppId(),
request.getTypedParameter("album", Album.class),
Iterables.getOnlyElement(albumIds), request.getToken());
}
/*
* Handles delete operations.
*
* Allowed end-points: /albums/{userId}/@self/{albumId}
*
* Examples: /albums/john.doe/@self/1
*/
@Operation(httpMethods = "DELETE")
public Future<?> delete(SocialRequestItem request) throws ProtocolException {
// Get user and album ID
Set<UserId> userIds = request.getUsers();
String albumId = request.getParameter("albumId");
// Enforce preconditions - userIds must contain exactly one element
HandlerPreconditions.requireNotEmpty(userIds, "No userId specified");
HandlerPreconditions.requireSingular(userIds, "Multiple userIds not supported");
// Service request
return service.deleteAlbum(Iterables.getOnlyElement(userIds),
request.getAppId(), albumId, request.getToken());
}
/*
* Retrieves supported fields for the albums service.
*/
@Operation(httpMethods = "GET", path = "/@supportedFields")
public List<Object> supportedFields(RequestItem request) {
String container = Objects.firstNonNull(request.getToken().getContainer(),
ContainerConfig.DEFAULT_CONTAINER);
return config.getList(container,
"${Cur['gadgets.features'].opensocial.supportedFields.album}");
}
}