com.google.api.client.googleapis.xml.atom.package-info Maven / Gradle / Ivy
/*
* Copyright (c) 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.
*/
/**
* 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:
*
*
*
<?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):
*
*
*
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:
*
*
*
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:
*
*
*
private static HttpTransport setUpTransport() throws IOException {
HttpTransport result = new NetHttpTransport();
GoogleUtils.useMethodOverride(result);
GoogleHeaders headers = new GoogleHeaders();
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:
*
*
*
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:
*
*
*
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:
*
*
*
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:
*
*
*
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:
*
*
*
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.
*
*
*
* Warning: this package is experimental, and its content may be changed in incompatible ways or
* possibly entirely removed in a future version of the library
*
*
* @since 1.0
* @author Yaniv Inbar
*/
package com.google.api.client.googleapis.xml.atom;