com.google.api.client.googleapis.xml.atom.package-info Maven / Gradle / Ivy
/*
* Copyright 2010 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.
*/
/**
* {@link com.google.api.client.util.Beta}
* Utilities for Google's Atom XML implementation (see detailed package specification).
*
* Package Specification
*
* User-defined Partial XML data models allow you to defined Plain Old Java Objects (POJO's) to
* define how the library should parse/serialize XML. Each field that should be included must have
* an @{@link com.google.api.client.util.Key} annotation. The field can be of any visibility
* (private, package private, protected, or public) and must not be static.
*
*
The optional value parameter of this @{@link com.google.api.client.util.Key} annotation
* specifies the XPath name to use to represent the field. For example, an XML attribute a
*
has an XPath name of @a
, an XML element <a>
has an XPath
* name of
* a
*
, and an XML text content has an XPath name of text()
. These are named based
* on their usage with the partial
* response/update syntax for Google API's. If the @{@link com.google.api.client.util.Key}
* annotation is missing, the default is to use the Atom XML namespace and the Java field's name as
* the local XML name. By default, the field name is used as the JSON key. Any unrecognized XML is
* normally simply ignored and not stored. If the ability to store unknown keys is important, use
* {@link com.google.api.client.xml.GenericXml}.
*
*
Let's take a look at a typical partial Atom XML album feed from the Picasa Web Albums Data
* API:
*
*
{@code
* <?xml version='1.0' encoding='utf-8'?>
* <feed xmlns='http://www.w3.org/2005/Atom'
* xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/'
* xmlns:gphoto='http://schemas.google.com/photos/2007'>
* <link rel='http://schemas.google.com/g/2005#post'
* type='application/atom+xml'
* href='http://picasaweb.google.com/data/feed/api/user/liz' />
* <author>
* <name>Liz</name>
* </author>
* <openSearch:totalResults>1</openSearch:totalResults>
* <entry gd:etag='"RXY8fjVSLyp7ImA9WxVVGE8KQAE."'>
* <category scheme='http://schemas.google.com/g/2005#kind'
* term='http://schemas.google.com/photos/2007#album' />
* <title>lolcats</title>
* <summary>Hilarious Felines</summary>
* <gphoto:access>public</gphoto:access>
* </entry>
* </feed>
* }
*
* Here's one possible way to design the Java data classes for this (each class in its own Java
* file):
*
*
{@code
* import com.google.api.client.util.*;
* import java.util.List;
*
* public class Link {
*
* @Key("@href")
* public String href;
*
* @Key("@rel")
* public String rel;
*
* public static String find(List<Link> links, String rel) {
* if (links != null) {
* for (Link link : links) {
* if (rel.equals(link.rel)) {
* return link.href;
* }
* }
* }
* return null;
* }
* }
*
* public class Category {
*
* @Key("@scheme")
* public String scheme;
*
* @Key("@term")
* public String term;
*
* public static Category newKind(String kind) {
* Category category = new Category();
* category.scheme = "http://schemas.google.com/g/2005#kind";
* category.term = "http://schemas.google.com/photos/2007#" + kind;
* return category;
* }
* }
*
* public class AlbumEntry {
*
* @Key
* public String summary;
*
* @Key
* public String title;
*
* @Key("gphoto:access")
* public String access;
*
* public Category category = newKind("album");
*
* private String getEditLink() {
* return Link.find(links, "edit");
* }
* }
*
* public class Author {
*
* @Key
* public String name;
* }
*
* public class AlbumFeed {
*
* @Key
* public Author author;
*
* @Key("openSearch:totalResults")
* public int totalResults;
*
* @Key("entry")
* public List<AlbumEntry> photos;
*
* @Key("link")
* public List<Link> links;
*
* private String getPostLink() {
* return Link.find(links, "http://schemas.google.com/g/2005#post");
* }
* }
* }
*
* You can also use the @{@link com.google.api.client.util.Key} annotation to defined query
* parameters for a URL. For example:
*
*
{@code
* public class PicasaUrl extends GoogleUrl {
*
* @Key("max-results")
* public Integer maxResults;
*
* @Key
* public String kinds;
*
* public PicasaUrl(String url) {
* super(url);
* }
*
* public static PicasaUrl fromRelativePath(String relativePath) {
* PicasaUrl result = new PicasaUrl(PicasaWebAlbums.ROOT_URL);
* result.path += relativePath;
* return result;
* }
* }
* }
*
* To work with a Google API, you first need to set up the {@link
* com.google.api.client.http.HttpTransport}. For example:
*
*
{@code
* private static HttpTransport setUpTransport() throws IOException {
* HttpTransport result = new NetHttpTransport();
* GoogleUtils.useMethodOverride(result);
* HttpHeaders headers = new HttpHeaders();
* headers.setApplicationName("Google-PicasaSample/1.0");
* headers.gdataVersion = "2";
* AtomParser parser = new AtomParser();
* parser.namespaceDictionary = PicasaWebAlbumsAtom.NAMESPACE_DICTIONARY;
* transport.addParser(parser);
* // insert authentication code...
* return transport;
* }
* }
*
* Now that we have a transport, we can execute a partial GET request to the Picasa Web Albums
* API and parse the result:
*
*
{@code
* public static AlbumFeed executeGet(HttpTransport transport, PicasaUrl url) throws IOException {
* url.fields = GoogleAtom.getFieldsFor(AlbumFeed.class);
* url.kinds = "photo";
* url.maxResults = 5;
* HttpRequest request = transport.buildGetRequest();
* request.url = url;
* return request.execute().parseAs(AlbumFeed.class);
* }
* }
*
* If the server responds with an error the {@link
* com.google.api.client.http.HttpRequest#execute} method will throw an {@link
* com.google.api.client.http.HttpResponseException}, which has an {@link
* com.google.api.client.http.HttpResponse} field which can be parsed the same way as a success
* response inside of a catch block. For example:
*
*
{@code
* try {
* ...
* } catch (HttpResponseException e) {
* if (e.response.getParser() != null) {
* Error error = e.response.parseAs(Error.class);
* // process error response
* } else {
* String errorContentString = e.response.parseAsString();
* // process error response as string
* }
* throw e;
* }
* }
*
* To update an album, we use the transport to execute an efficient partial update request using
* the PATCH method to the Picasa Web Albums API:
*
*
{@code
* public AlbumEntry executePatchRelativeToOriginal
* (HttpTransport transport, AlbumEntry original) throws IOException {
* HttpRequest request = transport.buildPatchRequest();
* request.setUrl(getEditLink());
* request.headers.ifMatch = etag;
* AtomPatchRelativeToOriginalContent content = new AtomPatchRelativeToOriginalContent();
* content.namespaceDictionary = PicasaWebAlbumsAtom.NAMESPACE_DICTIONARY;
* content.originalEntry = original;
* content.patchedEntry = this;
* request.content = content;
* return request.execute().parseAs(AlbumEntry.class);
* }
*
* private static AlbumEntry updateTitle
* (HttpTransport transport, AlbumEntry album) throws IOException {
* AlbumEntry patched = album.clone();
* patched.title = "An alternate title";
* return patched.executePatchRelativeToOriginal(transport, album);
* }
* }
*
* To insert an album, we use the transport to execute a POST request to the Picasa Web Albums
* API:
*
*
{@code
* public AlbumEntry insertAlbum(HttpTransport transport, AlbumEntry entry) throws IOException {
* HttpRequest request = transport.buildPostRequest();
* request.setUrl(getPostLink());
* AtomContent content = new AtomContent();
* content.namespaceDictionary = PicasaWebAlbumsAtom.NAMESPACE_DICTIONARY;
* content.entry = entry;
* request.content = content;
* return request.execute().parseAs(AlbumEntry.class);
* }
* }
*
* To delete an album, we use the transport to execute a DELETE request to the Picasa Web Albums
* API:
*
*
{@code
* public void executeDelete(HttpTransport transport) throws IOException {
* HttpRequest request = transport.buildDeleteRequest();
* request.setUrl(getEditLink());
* request.headers.ifMatch = etag;
* request.execute().ignore();
* }
* }
*
* NOTE: As you might guess, the library uses reflection to populate the user-defined data model.
* It's not quite as fast as writing the wire format parsing code yourself can potentially be, but
* it's a lot easier.
*
*
NOTE: If you prefer to use your favorite XML parsing library instead (there are many of them),
* that's supported as well. Just call {@link com.google.api.client.http.HttpRequest#execute()} and
* parse the returned byte stream.
*
* @since 1.0
* @author Yaniv Inbar
*/
@com.google.api.client.util.Beta
package com.google.api.client.googleapis.xml.atom;