/* Copyright (c) 2006 Google Inc.
*
* Licensed 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 com.google.api.gbase.client;
import com.google.gdata.client.Query;
import com.google.gdata.client.Service;
import com.google.gdata.client.batch.BatchInterruptedException;
import com.google.gdata.client.media.MediaService;
import com.google.gdata.data.DateTime;
import com.google.gdata.data.BaseEntry;
import com.google.gdata.data.BaseFeed;
import com.google.gdata.data.IEntry;
import com.google.gdata.data.IFeed;
import com.google.gdata.data.ExtensionProfile;
import com.google.gdata.data.batch.BatchOperationType;
import com.google.gdata.data.batch.BatchUtils;
import com.google.gdata.util.ServiceException;
import com.google.gdata.util.Version;
import java.io.IOException;
import java.net.URL;
import java.util.List;
/**
* Creates a Google data service with extensions
* specific to Google Base.
*
* The methods returning Atom feeds and entries in this class
* default to returning instances of {@link GoogleBaseFeed} and
* {@link GoogleBaseEntry}.
*
* <h4>Usage example<h4>
* <pre>
* GoogleBaseService service = new GoogleBaseService("mycompany-myapp-1.0");
* service.setUserCredentials(username, password);
* GoogleBaseQuery query = new GoogleBaseQuery(...);
* query.setGoogleBaseQuery(...);
* GoogleBaseFeed feed = service.query(query);
* </pre>
*/
public class GoogleBaseService extends MediaService {
/**
* The official name of the service.
*/
public static final String GOOGLE_BASE_SERVICE = "gbase";
/**
* Version of this service.
* @see #getServiceVersion()
*/
public static final String GOOGLE_BASE_SERVICE_VERSION = "GBase-Java/" +
GoogleBaseService.class.getPackage().getImplementationVersion();
/** The Versions class contains all released versions of the Google Base API */
public static class Versions {
/**
* Version 1 of the Google Base API. This is the initial version of the API and is
* based upon Version 1 of the GData Protocol.
*/
public static final Version V1 =
new Version(GoogleBaseService.class, "1.0", Service.Versions.V1);
/**
* Version 2 of the Google Base API. This version of the API adds full compliance
* with the Atom Publishing Protocol and is based upon Version 2 of the GData protocol.
*/
public static final Version V2 =
new Version(GoogleBaseService.class, "2.0", Service.Versions.V2);
}
/**
* Version 1 is the current default version for GoogleBaseService.
*/
public static final Version DEFAULT_VERSION =
Service.initServiceVersion(GoogleBaseService.class, GoogleBaseService.Versions.V2);
/** Name of the application passed to the constructor. */
protected String application;
/**
* Creates a GoogleBaseService connecting to the default
* authentication domain (www.google.com) using the HTTPS.
*
* @param applicationName the name of the client application accessing the
* service. Application names should preferably have
* the format [company-id]-[app-name]-[app-version].
* The name will be used by the Google servers to
* monitor the source of authentication.
*/
public GoogleBaseService(String applicationName) {
super(GOOGLE_BASE_SERVICE, applicationName);
this.application = applicationName;
addExtensions();
}
/**
* Creates a GoogleBaseService connecting to the default
* authentication domain (www.google.com) using the HTTPS.
*
* @param applicationName the name of the client application accessing the
* service. Application names should preferably have
* the format [company-id]-[app-name]-[app-version].
* The name will be used by the Google servers to
* monitor the source of authentication.
* @param developerKey developer key (ignored)
*/
public GoogleBaseService(String applicationName, String developerKey) {
this(applicationName);
}
/**
* Creates a GoogleBaseService connecting to a specific
* authentication domain using a specific protocol.
*
* @param applicationName the name of the client application accessing the
* service. Application names should preferably have
* the format [company-id]-[app-name]-[app-version].
* The name will be used by the Google servers to
* monitor the source of authentication.
* @param protocol name of protocol to use for authentication
* ("http"/"https")
* @param domainName the name of the domain hosting the login handler
*/
public GoogleBaseService(String applicationName,
String protocol,
String domainName) {
super(GOOGLE_BASE_SERVICE, applicationName, protocol, domainName);
this.application = applicationName;
addExtensions();
}
/**
* Creates a GoogleBaseService connecting to a specific
* authentication domain using a specific protocol.
*
* @param applicationName the name of the client application accessing the
* service. Application names should preferably have
* the format [company-id]-[app-name]-[app-version].
* The name will be used by the Google servers to
* monitor the source of authentication.
* @param developerKey developer key (ignored)
* @param protocol name of protocol to use for authentication
* ("http"/"https")
* @param domainName the name of the domain hosting the login handler
*/
public GoogleBaseService(String applicationName,
String developerKey,
String protocol,
String domainName) {
this(applicationName, protocol, domainName);
}
/**
* Returns the Google Base feed associated with a particular feed URL, if
* it's been modified since the specified date.
*
* @param feedUrl the URL associated with a feed. This URL can include
* GData query parameters.
* @param ifModifiedSince used to set a precondition date that indicates the
* feed should be returned only if it has been modified
* after the specified date. A value of {@code null}
* indicates no precondition.
* @return Feed resource referenced by the input URL.
* @throws IOException error sending request or reading the feed.
* @throws com.google.gdata.util.NotModifiedException if the feed resource
* has not been modified since the specified precondition date.
* @throws com.google.gdata.util.ParseException error parsing the returned
* feed data.
* @throws com.google.gdata.util.ResourceNotFoundException invalid feed URL.
* @throws ServiceException system error retrieving feed.
* @see #getFeed(java.net.URL, Class, com.google.gdata.data.DateTime)
*/
public GoogleBaseFeed getFeed(URL feedUrl, DateTime ifModifiedSince)
throws IOException, ServiceException {
return getFeed(feedUrl, GoogleBaseFeed.class, ifModifiedSince);
}
/**
* Returns the Google base feed associated with a particular feed URL.
*
* @param feedUrl the URL associated with a feed. This URL can include
* GData query parameters.
* @return Feed resource referenced by the input URL.
* @throws IOException error sending request or reading the feed.
* @throws com.google.gdata.util.ParseException error parsing the returned
* feed data.
* @throws com.google.gdata.util.ResourceNotFoundException invalid feed URL.
* @throws ServiceException system error retrieving feed.
* @see #getFeed(java.net.URL, Class)
*/
public GoogleBaseFeed getFeed(URL feedUrl)
throws IOException, ServiceException {
return getFeed(feedUrl, GoogleBaseFeed.class);
}
/**
* Returns the Google base media feed associated with the specified feed URL.
* For the call to be valid, the user must be authenticated and own the item.
* The Google Base item has the link to its media feed registered as a
* {@link com.google.gdata.data.extensions.FeedLink} extension with the
* {@code media} relation.
*
* @throws IOException error sending request or reading the feed.
* @throws com.google.gdata.util.ParseException error parsing the returned
* feed data.
* @throws com.google.gdata.util.ResourceNotFoundException invalid feed URL.
* @throws ServiceException system error retrieving feed.
* @see #getFeed(java.net.URL, Class, com.google.gdata.data.DateTime)
*/
public GoogleBaseMediaFeed getMediaFeed(URL feedUrl) throws IOException, ServiceException {
return getFeed(feedUrl, GoogleBaseMediaFeed.class);
}
/**
* Returns the Google Base media feed associated with a particular feed URL,
* if it's been modified since the specified date.
*
* @param feedUrl the URL associated with a media feed for one particular
* item.
* @param ifModifiedSince used to set a precondition date that indicates the
* feed should be returned only if it has been modified after the
* specified date. A value of {@code null} indicates no
* precondition.
* @return Feed resource referenced by the input URL.
* @throws IOException error sending request or reading the feed.
* @throws com.google.gdata.util.NotModifiedException if the feed resource has
* not been modified since the specified precondition date.
* @throws com.google.gdata.util.ParseException error parsing the returned
* feed data.
* @throws com.google.gdata.util.ResourceNotFoundException invalid feed URL.
* @throws ServiceException system error retrieving feed.
* @see #getFeed(java.net.URL, Class, com.google.gdata.data.DateTime)
*/
public GoogleBaseMediaFeed getMediaFeed(URL feedUrl, DateTime ifModifiedSince)
throws IOException, ServiceException {
return getFeed(feedUrl, GoogleBaseMediaFeed.class, ifModifiedSince);
}
/**
* Returns an Google Base entry instance, given the URL of the entry and an
* if-modified-since date.
*
* @param entryUrl resource URL for the entry.
* @param ifModifiedSince used to set a precondition date that indicates the
* entry should be returned only if it has been
* modified after the specified date. A value of
* {@code null} indicates no precondition.
* @return the entry referenced by the URL parameter.
* @throws IOException error communicating with the GData service.
* @throws com.google.gdata.util.NotModifiedException if the entry resource
* has not been modified after the specified precondition date.
* @throws com.google.gdata.util.ParseException error parsing the returned
* entry.
* @throws com.google.gdata.util.ResourceNotFoundException if the entry URL
* is not valid.
* @throws com.google.gdata.util.ServiceForbiddenException if the GData
* service cannot get the entry resource due to access constraints.
* @throws ServiceException if a system error occurred when retrieving
* the entry.
* @see #getEntry(java.net.URL, Class, DateTime)
*/
public GoogleBaseEntry getEntry(URL entryUrl, DateTime ifModifiedSince)
throws IOException, ServiceException {
return getEntry(entryUrl, GoogleBaseEntry.class, ifModifiedSince);
}
/**
* Returns an Google Base entry instance, given the URL of the entry.
*
* @param entryUrl resource URL for the entry.
* @return the entry referenced by the URL parameter.
* @throws IOException error communicating with the GData service.
* @throws com.google.gdata.util.ParseException error parsing the returned
* entry.
* @throws com.google.gdata.util.ResourceNotFoundException if the entry URL
* is not valid.
* @throws com.google.gdata.util.ServiceForbiddenException if the GData
* service cannot get the entry resource due to access constraints.
* @throws ServiceException if a system error occurred when retrieving
* the entry.
* @see #getEntry(java.net.URL, Class)
*/
public GoogleBaseEntry getEntry(URL entryUrl)
throws IOException, ServiceException {
return getEntry(entryUrl, GoogleBaseEntry.class);
}
/**
* Returns the media entry referenced by the entryUrl. If the URL is not
* pointing to a media entry, an exception will be thrown.
*
* @param entryUrl the url to the media entry.
* @return a media entry object representing the meta-data for the referenced
* media object (item image or attachment).
* @throws IOException error communicating with the GData service.
* @throws com.google.gdata.util.ParseException error parsing the returned
* entry.
* @throws com.google.gdata.util.ResourceNotFoundException if the entry URL is
* not valid.
* @throws com.google.gdata.util.ServiceForbiddenException if the GData
* service cannot get the entry resource due to access
* constraints.
* @throws ServiceException if a system error occurred when retrieving the
* entry
*/
public GoogleBaseMediaEntry getMediaEntry(URL entryUrl)
throws IOException, ServiceException {
return getEntry(entryUrl, GoogleBaseMediaEntry.class);
}
/**
* Returns the media entry referenced by the entryUrl, if it's been modified
* since the specified date.
*
* @param entryUrl the url to the media entry.
* @return a media entry object representing the meta-data for the referenced
* media object (item image or attachment).
* @throws IOException error communicating with the GData service.
* @throws com.google.gdata.util.NotModifiedException if the entry resource
* has not been modified after the specified precondition date.
* @throws com.google.gdata.util.ParseException error parsing the returned
* entry.
* @throws com.google.gdata.util.ResourceNotFoundException if the entry URL is
* not valid.
* @throws com.google.gdata.util.ServiceForbiddenException if the GData
* service cannot get the entry resource due to access
* constraints.
* @throws ServiceException if a system error occurred when retrieving the
* entry
*/
public GoogleBaseMediaEntry getMediaEntry(URL entryUrl, DateTime ifModifiedSince)
throws IOException, ServiceException {
return getEntry(entryUrl, GoogleBaseMediaEntry.class, ifModifiedSince);
}
/**
* Executes a GData query against the target service and returns the
* {@link GoogleBaseFeed} containing entries that match the query result, if
* it's been modified since the specified date.
*
* @param query Query instance defining target feed and query parameters,
* usually a {@link GoogleBaseQuery}
* @param ifModifiedSince used to set a precondition date that indicates the
* query result feed should be returned only if contains entries
* that have been modified after the specified date. A value of
* {@code null} indicates no precondition.
* @throws IOException error communicating with the GData service.
* @throws com.google.gdata.util.NotModifiedException if the query resource
* does not contain entries modified since the specified precondition
* date.
* @throws com.google.gdata.util.ServiceForbiddenException feed does not
* support the query.
* @throws com.google.gdata.util.ParseException error parsing the returned
* feed data.
* @throws ServiceException query request failed.
* @see #query(com.google.gdata.client.Query, Class, DateTime)
*/
public GoogleBaseFeed query(Query query, DateTime ifModifiedSince)
throws IOException, ServiceException {
return query(query, GoogleBaseFeed.class, ifModifiedSince);
}
/**
* Executes a GData query against the target service and returns the
* {@link com.google.gdata.data.Feed} containing entries that match the
* query result.
*
* @param query Query instance defining target feed and query parameters,
* usually a {@link GoogleBaseQuery}
* @throws IOException error communicating with the GData service.
* @throws com.google.gdata.util.NotModifiedException if the query resource
* does not contain entries modified since the specified precondition
* date.
* @throws com.google.gdata.util.ServiceForbiddenException feed does not
* support the query.
* @throws com.google.gdata.util.ParseException error parsing the returned
* feed data.
* @throws ServiceException query request failed.
*/
public GoogleBaseFeed query(Query query)
throws IOException, ServiceException {
return query(query, GoogleBaseFeed.class);
}
@Override
public <E extends IEntry> E update(URL url, E e)
throws IOException, ServiceException {
addApplicationAttribute(e);
return super.update(url, e);
}
@Override
public <E extends IEntry> E insert(URL url, E e)
throws IOException, ServiceException {
addApplicationAttribute(e);
return super.insert(url, e);
}
@Override
public <F extends IFeed> F batch(URL url, F f)
throws IOException, ServiceException, BatchInterruptedException {
addApplicationAttribute(f);
return super.batch(url, f);
}
/**
* Sets the application attribute using the name passed to the
* constructor.
*
* @param e
*/
private void addApplicationAttribute(IEntry iEntry) {
if (!(iEntry instanceof BaseEntry)) {
throw new IllegalArgumentException(
"Unexpected entry type: " + iEntry.getClass());
}
BaseEntry<?> e = (BaseEntry<?>) iEntry;
GoogleBaseAttributesExtension attrs = e.getExtension(GoogleBaseAttributesExtension.class);
if (attrs == null) {
return;
}
attrs.setApplication(application);
}
/**
* Sets the application attribute using the name passed to the constructor
* on a batch feed.
*
* @param batchFeed
*/
@SuppressWarnings("unchecked")
private void addApplicationAttribute(IFeed iFeed) {
if (! (iFeed instanceof BaseFeed)) {
throw new IllegalArgumentException("Unexpected feed type: " + iFeed);
}
BaseFeed<?, ?> batchFeed = (BaseFeed<?, ?>) iFeed;
BatchOperationType defaultType = BatchUtils.getBatchOperationType(batchFeed);
if (defaultType == null) {
defaultType = BatchOperationType.INSERT;
}
List<? extends BaseEntry> entries = batchFeed.getEntries();
for (BaseEntry<?> entry: entries) {
BatchOperationType type = BatchUtils.getBatchOperationType(entry);
if (type == null) {
type = defaultType;
}
if (type == BatchOperationType.INSERT ||
type == BatchOperationType.UPDATE) {
addApplicationAttribute(entry);
}
}
}
/**
* Adds Google Base extensions (g:namespaces) to a
* Google data service.
*/
private void addExtensions() {
ExtensionProfile extensionProfile = getExtensionProfile();
GoogleBaseNamespaces.declareAllExtensions(extensionProfile);
BatchUtils.declareExtensions(extensionProfile);
}
/**
* Returns the google base service version followed by the gdata
* service version.
*
* @return both versions, separated by a space
* @see #GOOGLE_BASE_SERVICE_VERSION
*/
@Override
public String getServiceVersion() {
return GOOGLE_BASE_SERVICE_VERSION + " " + super.getServiceVersion();
}
}