⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 basefeed.java

📁 google的gdata api包
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* 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.gdata.data;import com.google.gdata.util.common.xml.XmlWriter;import com.google.gdata.util.common.xml.XmlWriter.Namespace;import com.google.gdata.client.Query;import com.google.gdata.client.Service;import com.google.gdata.util.Namespaces;import com.google.gdata.util.NotModifiedException;import com.google.gdata.util.ParseException;import com.google.gdata.util.ServiceException;import com.google.gdata.util.XmlParser;import com.google.gdata.util.XmlParser.ElementHandler;import org.xml.sax.Attributes;import java.io.IOException;import java.io.InputStream;import java.io.Reader;import java.net.URL;import java.util.ArrayList;import java.util.Collection;import java.util.LinkedList;import java.util.List;import java.util.Vector;/** * The BaseFeed class is an abstract base class that represents a * generic GData feed object, based primarily on the data model for * an {@code <atom:feed>} element.  It is extended to represent * OpenSearch RSS channel elements, and also supports generalized * extensibility using a defined ExtensionProfile and/or by stored * extended data as an XmlBlob. * <p> * The BaseFeedClass is a generic class that is parameterized by the * type of Entry that will be contained within the feed.  The base * class contains all the necessary parsing and generation code for * feed extension data, but can be subclassed to create subtypes that * contain convenience APIs for accessing extension elements and * entries. * <p> * An instance can be initialized by parsing an Atom 1.0 feed * from a Reader or by directly initializing its component * elements.  It can generate an XML representation of the feed * to an XmlWriter in either Atom 1.0 or RSS 2.0 format. * <p> * Here is the Relax-NG schema that represents an Atom 1.0 * feed: * <pre> * AtomFeed = *  element atom:feed { *    atomCommonAttributes, *    (atomAuthor* *     atomCategory* *     atomContributor* *     atomGenerator? *     atomIcon? *     atomId *     atomLink* *     atomLogo? *     atomRights? *     atomSubtitle? *     atomTitle *     atomUpdated *     extensionElement*), *     atomEntry* *   } * </pre> * * Because the Feed schema differs from the Source schema only by the * presence of the entries, the Feed class derives its base property * model and parsing/generation implementations from the Source class. * <p> * The BaseFeed class implements the {@link Kind.Adaptable} interface, meaning * it is possible to create new {@link Kind.Adaptor} subtypes that defines * a custom extension model (and associated convience APIs) for a BaseFeed * subtypes that use Atom/RSS extensions to extend the content model for a * particular type of data. * <p> * An {@link Kind.Adaptor} subclass of BaseFeed should do the following: * <ul> * <li>Include a {@link Kind.Term} annotation on the class declaration that * defines the {@link Category} term value for the GData kind handled by the * adaptor.</li> * <li>Provide a constructor that takes a {@code Class} and {@code BaseFeed} * parameter as an argument that is used when adapting a generic feed type to * a more specific one.</li> * <li>Implement the {@link Kind.Adaptor#declareExtensions(ExtensionProfile)} * method and use it to declare the extension model for the adapted instance * within the profile passed as a parameter.   This is used to auto-extend * an extension profile when kind Category tags are found during parsing of * content.</li> * <li>Expose convenience APIs to retrieve and set extension attributes, with * an implementions that delegates to {@link ExtensionPoint} methods to * store/retrieve the extension data. * </ul> * * @param   <F> feed type associated with bound subtype. * @param   <E> entry type associated with bound subtype. *  *  */public abstract class BaseFeed<F extends BaseFeed, E extends BaseEntry>    extends Source    implements Kind.Adaptable, Kind.Adaptor {  /**   * The FeedState class provides a simple structure that encapsulates   * the attributes of an Atom feed that should be shared with a shallow   * copy if the feed is adapted to a more specific BaseFeed   * {@link Kind.Adaptor} subtypes.   * <p>   * <b>Note: Feed entries are not part of feed shared state, because   * the entry lists will need to be typed differently for adapted   * instances.</b>  This means that entries that are created, updated, or   * deleted in an adapted feed will not be reflected in the base feed   * used to construct it.  The reverse is also true: changes made to a base   * feed will not be reflected in any adapted instances of the feed.   *   * @see BaseFeed#BaseFeed(Class, BaseFeed)   */  protected static class FeedState {    /** Service associated with the feed. */    public Service service;    /** Specifies whether the feed can be posted to. */    public boolean canPost = true;    /** OpenSearch: number of search results (feed entries). */    public int totalResults = Query.UNDEFINED;    /** OpenSearch: start index. */    public int startIndex = Query.UNDEFINED;    /** OpenSearch: items per page. */    public int itemsPerPage = Query.UNDEFINED;    /** Adaptable helper */    public Kind.Adaptable adaptable = new Kind.AdaptableHelper();  }  /**   * Basic state for this feed.   May be shared across multiple adapted   * instances associated with the same logical feed.   */  protected FeedState feedState;  /**   * Class used to construct new entry instance, initialized at construction.   */  protected Class<? extends E> entryClass;  /** Feed entries. */  protected LinkedList<E> entries = new LinkedList<E>();  /**   * Copy constructor that initializes a new BaseFeed instance to have   * identical contents to another instance, using a shared reference to   * the same {@link FeedState}.  {@link Kind.Adaptor} subclasses   * of {@code BaseFeed} can use this constructor to create adaptor   * instances of an entry that share state with the original.   *   * @param entryClass   *          Class used to construct new Entry instances for the Feed.   */  protected BaseFeed(Class<? extends E> entryClass) {    feedState = new FeedState();    this.entryClass = entryClass;  }  /**   * Copy constructor that initializes a new BaseFeed instance to have   * identical contents to another instance, using a shared reference to   * the same {@link FeedState}.  {@link Kind.Adaptor} subclasses   * of {@code BaseFeed} can use this constructor to create adaptor   * instances of a feed that share state with the original.   */  protected BaseFeed(Class<? extends E> entryClass, BaseFeed sourceFeed) {    super(sourceFeed);    feedState = sourceFeed.feedState;    this.entryClass = entryClass;  }  /**   * {@inheritDoc}   * <p>   * The implementation of this method for BaseFeed will declare any   * extensions associated with the contained entry type.   */  public void declareExtensions(ExtensionProfile extProfile) {    // Create an instance of the associated entry class and declare its    // extensions.    E entry = createEntry();    extProfile.addDeclarations(entry);  }  /**   * Returns that GData {@link Service} instance tassociated with this feed.   */  public Service getService() { return feedState.service; }  /**   * Sets that GData {@link Service} instance associated with this feed.   */  public void setService(Service v) {    feedState.service = v;    // Propagate service information to nested entries    for (E entry : entries) {      entry.setService(v);    }  }  /**   * Gets the property that indicates if it is possible to post new entries   * to the feed.   */  public boolean getCanPost() { return feedState.canPost; }  /**   * Sets the property that indicates if it is possible to post new entries   * to the feed.   */  public void setCanPost(boolean v) { feedState.canPost = v; }  /**   * Gets the total number of results associated with this feed.  The value   * may be larger than the number of contained entries for paged feeds.   * A value of {@link Query#UNDEFINED} indicates the total size is undefined.   */  public int getTotalResults() { return feedState.totalResults; }  /**   * Sets the total number of results associated with this feed.  The value   * may be larger than the number of contained entries for paged feeds.   * A value of {@link Query#UNDEFINED} indicates the total size is undefined.   */  public void setTotalResults(int v) { feedState.totalResults = v; }  /**   * Gets the starting index of the contained entries for paged feeds.   * A value of {@link Query#UNDEFINED} indicates the start index is undefined.   */  public int getStartIndex() { return feedState.startIndex; }  /**   * Sets the starting index of the contained entries for paged feeds.   * A value of {@link Query#UNDEFINED} indicates the start index is undefined.   */  public void setStartIndex(int v) { feedState.startIndex = v; }  /**   * Gets the number of items that will be returned per page for paged feeds.   * A value of {@link Query#UNDEFINED} indicates the page item count is   * undefined.   */  public int getItemsPerPage() { return feedState.itemsPerPage; }  /**   * Sets the number of items that will be returned per page for paged feeds.   * A value of {@link Query#UNDEFINED} indicates the page item count is   * undefined.   */  public void setItemsPerPage(int v) { feedState.itemsPerPage = v; }  public List<E> getEntries() { return entries; }  // Implementation of Adaptable methods  //  public void addAdaptor(Kind.Adaptor adaptor) {    feedState.adaptable.addAdaptor(adaptor);  }  public Collection<Kind.Adaptor> getAdaptors() {    return feedState.adaptable.getAdaptors();  }  public <A extends Kind.Adaptor> A getAdaptor(Class<A> adaptorClass) {    return feedState.adaptable.getAdaptor(adaptorClass);  }  /**   * Creates a new entry for the feed.   */  public E createEntry() {    E entry;    try {      entry = entryClass.newInstance();    } catch (InstantiationException e) {      throw new IllegalStateException(e);    } catch (IllegalAccessException e) {      throw new IllegalStateException(e);    }    // Propagate the associated service (if any)    if (feedState.service != null) {      entry.setService(feedState.service);    }    return entry;  }  /** Returns the entry post link for the feed. */  public Link getEntryPostLink() {    Link postLink = getLink(Link.Rel.ENTRY_POST, Link.Type.ATOM);    return postLink;  }  /** Returns the self link for the feed. */  public Link getSelfLink() {    Link postLink = getLink(Link.Rel.SELF, Link.Type.ATOM);    return postLink;  }  /**   * Returns the current representation of the feed by requesting it from   * the associated service using the feed's self link.   *   * @return the current state of the feed.   */  public F getSelf() throws IOException, ServiceException {    if (feedState.service == null) {      throw new ServiceException("Feed is not associated with a GData service");    }    Link selfLink = getSelfLink();    if (selfLink == null) {      throw new UnsupportedOperationException("Feed cannot be retrieved");    }    URL feedUrl = new URL(selfLink.getHref());    try {      return (F) feedState.service.getFeed(feedUrl, this.getClass(),          srcState.updated);    } catch (NotModifiedException e) {      return (F) this;    }  }  /**   * Inserts a new Entry into the feed, if the feed is currently   * associated with a Service.   *   * @return the inserted Entry returned by the Service.   *   * @throws ServiceException   *           If there is no associated GData service or the service is   *           unable to perform the insertion.   *   * @throws UnsupportedOperationException   *           If insert is not supported for the target feed.   *   * @throws IOException   *           If there is an error communicating with the GData service.   */  public <T extends E> T insert(T newEntry)      throws ServiceException, IOException {    if (feedState.service == null) {      throw new ServiceException(          "Entry is not associated with a GData service");    }    Link postLink = getEntryPostLink();    if (postLink == null) {      throw new UnsupportedOperationException("Media cannot be inserted");    }    URL postUrl = new URL(postLink.getHref());    return feedState.service.insert(postUrl, newEntry);  }  /**   * Generates XML in the Atom format.   *   * @param   w   *            Output writer.   *   * @param   extProfile   *            Extension profile.   *   * @throws  IOException   */  public void generateAtom(XmlWriter w,                           ExtensionProfile extProfile) throws IOException {    generateFeedStart(extProfile, w, null);    generateEntries(w, extProfile);    generateFeedEnd(w);  }  private void generateEntries(XmlWriter w, ExtensionProfile extProfile) throws      IOException {    // Generate all entries    w.startRepeatingElement();    for (E entry : entries) {      entry.generateAtom(w, extProfile);    }    w.endRepeatingElement();  }  /**   * Closes everything that was opened by   * {@link #generateFeedStart}.   *   * @param w   * @throws IOException   */  public void generateFeedEnd(XmlWriter w) throws IOException {    w.endElement(Namespaces.atomNs, "feed");  }  /**   * Generates everything that's in the feed up and not including to the   * entries.  The idea is to use generateStart(), write the entries end then   * call {@link #generateFeedEnd(com.google.gdata.util.common.xml.XmlWriter)}   * to avoid having to add entries to a list and keep them in memory.   *   * @param extProfile   * @param w   * @param namespaces extra namespace declarations   * @throws IOException   */  public void generateFeedStart(ExtensionProfile extProfile,                                XmlWriter w,                                Collection<Namespace> namespaces) throws      IOException {    Vector<Namespace> nsDecls =      new Vector<Namespace>(namespaceDeclsAtom);    nsDecls.addAll(extProfile.getNamespaceDecls());    generateStartElement(w, Namespaces.atomNs, "feed", null, nsDecls);    // Generate base feed elements    generateInnerAtom(w, extProfile);    // Generate OpenSearch elements    if (feedState.totalResults != Query.UNDEFINED) {      w.simpleElement(Namespaces.openSearchNs, "totalResults", null,                      String.valueOf(feedState.totalResults));    }    if (feedState.startIndex != Query.UNDEFINED) {      w.simpleElement(Namespaces.openSearchNs, "startIndex", null,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -