com.google.gdata.model.transforms.atom.AtomRssTransforms.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gdata.model.transforms.atom.AtomRssTransforms.java

Source

/**
 * Mule Google Api Commons
 *
 * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 *
 * The software in this package is published under the terms of the CPAL v1.0
 * license, a copy of which has been included with this distribution in the
 * LICENSE.txt file.
 */

package com.google.gdata.model.transforms.atom;

import static com.google.gdata.model.MetadataContext.RSS;

import com.google.common.collect.Lists;
import com.google.gdata.util.common.xml.XmlNamespace;
import com.google.gdata.util.common.xml.XmlWriter;
import com.google.gdata.util.common.xml.XmlWriter.Attribute;
import com.google.gdata.data.DateTime;
import com.google.gdata.data.ILink.Rel;
import com.google.gdata.model.Element;
import com.google.gdata.model.ElementMetadata;
import com.google.gdata.model.MetadataRegistry;
import com.google.gdata.model.MetadataValueTransform;
import com.google.gdata.model.QName;
import com.google.gdata.model.Metadata.VirtualValue;
import com.google.gdata.model.atom.Author;
import com.google.gdata.model.atom.Category;
import com.google.gdata.model.atom.Content;
import com.google.gdata.model.atom.Contributor;
import com.google.gdata.model.atom.Entry;
import com.google.gdata.model.atom.Feed;
import com.google.gdata.model.atom.Link;
import com.google.gdata.model.atom.OutOfLineContent;
import com.google.gdata.model.atom.Person;
import com.google.gdata.model.atom.Source;
import com.google.gdata.model.atom.TextContent;
import com.google.gdata.model.atom.Source.Generator;
import com.google.gdata.model.atompub.Edited;
import com.google.gdata.model.gd.GdAttributes;
import com.google.gdata.util.ContentType;
import com.google.gdata.util.Namespaces;
import com.google.gdata.util.ParseException;
import com.google.gdata.wireformats.XmlGenerator;
import com.google.gdata.wireformats.XmlWireFormatProperties;

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
 * RSS transforms for atom.  This contains the transforms required to output
 * atom classes in RSS using the new data model.
 *
 * 
 */
public class AtomRssTransforms {

    // Constants for our rss names.
    private static final QName DOMAIN = new QName("domain");
    private static final QName CATEGORY = new QName(Namespaces.rssNs, "category");
    private static final QName ITEM = new QName(Namespaces.rssNs, "item");
    private static final QName GUID = new QName(Namespaces.rssNs, "guid");
    private static final QName TITLE = new QName(Namespaces.rssNs, "title");
    private static final QName PUB_DATE = new QName(Namespaces.rssNs, "pubDate");
    private static final QName AUTHOR = new QName(Namespaces.rssNs, "author");
    private static final QName RSS_NAME = new QName(Namespaces.rssNs, "rss");
    private static final QName DESCRIPTION = new QName(Namespaces.rssNs, "description");
    private static final QName LAST_BUILD_DATE = new QName(Namespaces.rssNs, "lastBuildDate");
    private static final QName COPYRIGHT = new QName(Namespaces.rssNs, "copyright");
    private static final QName MANAGING_EDITOR = new QName(Namespaces.rssNs, "managingEditor");
    private static final QName GENERATOR = new QName(Namespaces.rssNs, "generator");

    /**
     * Add the RSS transforms to the default metadata trees.
     */
    public static void addTransforms(MetadataRegistry registry) {
        addCategoryTransforms(registry);
        addContentTransforms(registry);
        addEntryTransforms(registry);
        addEntryOutOfLineContentTransforms(registry);
        addFeedTransforms(registry);
        addLinkTransforms(registry);
        addSourceTransforms(registry);
        addPersonTransforms(registry);
        addGeneratorTransforms(registry);
        addAppEditedTransforms(registry);
    }

    private static void addCategoryTransforms(MetadataRegistry registry) {
        registry.build(Category.KEY, RSS).setName(CATEGORY)
                .setVirtualValue(new MetadataValueTransform(Category.TERM, Category.LABEL));

        registry.build(Category.KEY, Category.SCHEME, RSS).setName(DOMAIN);

        registry.build(Category.KEY, Category.LABEL, RSS).setVisible(false);

        registry.build(Category.KEY, Category.TERM, RSS).setVisible(false);
    }

    private static void addContentTransforms(MetadataRegistry registry) {
        registry.build(TextContent.KEY, RSS).setName(DESCRIPTION).whitelistAttributes();
        registry.build(TextContent.CONSTRUCT, RSS).whitelistAttributes();
    }

    private static void addEntryTransforms(MetadataRegistry registry) {
        registry.build(Entry.KEY, RSS).setName(ITEM);

        registry.build(Entry.KEY, GdAttributes.ETAG, RSS).setVisible(false);

        XmlWireFormatProperties properties = new XmlWireFormatProperties();
        properties.setElementGenerator(new XmlGenerator.XmlElementGenerator() {
            @Override
            protected List<Attribute> getAttributes(Element e, ElementMetadata<?, ?> metadata) {
                List<Attribute> attrs = super.getAttributes(e, metadata);
                if (attrs == null) {
                    attrs = Lists.newArrayListWithExpectedSize(1);
                }
                attrs.add(new Attribute("isPermaLink", "false"));
                return attrs;
            }
        });
        registry.build(Entry.KEY, Entry.ID, RSS).setName(GUID).setProperties(properties);

        registry.build(Entry.KEY, Entry.TITLE, RSS).setName(TITLE);

        registry.build(Entry.KEY, Entry.PUBLISHED, RSS).setName(PUB_DATE).setVirtualValue(new VirtualValue() {
            public Object generate(Element element, ElementMetadata<?, ?> metadata) {
                DateTime date = element.getTextValue(Entry.PUBLISHED);
                return date == null ? "" : date.toStringRfc822();
            }

            public void parse(Element element, ElementMetadata<?, ?> metadata, Object value) throws ParseException {
                DateTime parsed = DateTime.parseRfc822(value.toString());
                element.setTextValue(parsed);
            }
        });

        XmlWireFormatProperties personProperties = new XmlWireFormatProperties();
        personProperties.setElementGenerator(new XmlGenerator.XmlElementGenerator() {
            @Override
            public boolean startElement(XmlWriter xw, Element parent, Element e, ElementMetadata<?, ?> metadata)
                    throws IOException {
                if (!(e instanceof Person)) {
                    return super.startElement(xw, parent, e, metadata);
                }

                Person person = (Person) e;
                String email = person.getEmail();
                String name = person.getName();

                StringBuilder text = new StringBuilder();
                boolean hasEmail = email != null;

                if (hasEmail) {
                    text.append(email);
                }

                if (name != null) {
                    if (hasEmail) {
                        text.append(" (");
                    }
                    text.append(name);
                    if (hasEmail) {
                        text.append(")");
                    }
                }

                QName xmlName = getName(e, metadata);
                xw.simpleElement(xmlName.getNs(), xmlName.getLocalName(), null, text.toString());
                return false;
            }

            @Override
            public void textContent(XmlWriter xw, Element e, ElementMetadata<?, ?> metadata) {
            }

            @Override
            public void endElement(XmlWriter xw, Element e, ElementMetadata<?, ?> metadata) {
            }
        });

        registry.build(Entry.KEY, Author.KEY, RSS).setName(AUTHOR).setProperties(personProperties);

        registry.build(Entry.KEY, Contributor.KEY, RSS).setName(AUTHOR).setProperties(personProperties);

        registry.build(Entry.KEY, Entry.RIGHTS, RSS).setVisible(false);
    }

    private static void addEntryOutOfLineContentTransforms(MetadataRegistry registry) {
        XmlWireFormatProperties properties = new XmlWireFormatProperties();
        properties.setElementGenerator(new XmlGenerator.XmlElementGenerator() {
            @Override
            public boolean startElement(XmlWriter xw, Element parent, Element e, ElementMetadata<?, ?> metadata)
                    throws IOException {
                if (!(e instanceof OutOfLineContent)) {
                    return super.startElement(xw, parent, e, metadata);
                }

                OutOfLineContent content = (OutOfLineContent) e;
                ContentType type = content.getMimeType();
                URI src = content.getSrc();
                generateEnclosure(xw, type == null ? null : type.getMediaType(),
                        src == null ? null : src.toString(), content.getLength());
                return false;
            }

            @Override
            public void textContent(XmlWriter xw, Element e, ElementMetadata<?, ?> metadata) {
            }

            @Override
            public void endElement(XmlWriter xw, Element e, ElementMetadata<?, ?> metadata) {
            }
        });

        registry.build(OutOfLineContent.KEY, RSS).setProperties(properties);
    }

    private static void addFeedTransforms(final MetadataRegistry registry) {
        registry.build(Feed.KEY, GdAttributes.ETAG, RSS).setVisible(false);

        XmlWireFormatProperties properties = new XmlWireFormatProperties();
        properties.setElementGenerator(new XmlGenerator.XmlElementGenerator() {
            @Override
            public boolean startElement(XmlWriter xw, Element parent, Element e, ElementMetadata<?, ?> metadata)
                    throws IOException {

                Collection<XmlNamespace> namespaces = getNamespaces(parent, e, metadata);
                List<XmlWriter.Attribute> attrs = getAttributes(e, metadata);
                if (attrs == null) {
                    attrs = Lists.newArrayList();
                }
                attrs.add(new Attribute("version", "2.0"));

                xw.startElement(Namespaces.rssNs, "rss", attrs, namespaces);
                xw.startElement(Namespaces.rssNs, "channel", null, null);

                if (!e.hasElement(Source.SUBTITLE) && !e.hasElement(Content.KEY)) {
                    // To preserve strict RSS2 compliance and backward compatibility:
                    // since atom feeds do not require a subtitle or text content, put in
                    // an empty description into RSS. This keeps RSS2 validators happy
                    xw.simpleElement(Namespaces.rssNs, "description", null, "");
                }
                return true;
            }

            @Override
            public void endElement(XmlWriter xw, Element e, ElementMetadata<?, ?> metadata) throws IOException {
                xw.endElement(Namespaces.rssNs, "channel");
                super.endElement(xw, e, metadata);
            }
        });
        registry.build(Feed.KEY, RSS).setName(RSS_NAME).setProperties(properties);

        registry.build(Feed.KEY, Feed.UPDATED, RSS).setName(LAST_BUILD_DATE).setVirtualValue(new VirtualValue() {
            public Object generate(Element element, ElementMetadata<?, ?> metadata) {
                DateTime date = element.getTextValue(Feed.UPDATED);
                return date == null ? "" : date.toStringRfc822();
            }

            public void parse(Element element, ElementMetadata<?, ?> metadata, Object value) throws ParseException {
                DateTime parsed = DateTime.parseRfc822(value.toString());
                element.setTextValue(parsed);
            }
        });
    }

    private static void addLinkTransforms(MetadataRegistry registry) {
        XmlWireFormatProperties properties = new XmlWireFormatProperties();
        properties.setElementGenerator(new XmlGenerator.XmlElementGenerator() {
            @Override
            public boolean startElement(XmlWriter xw, Element parent, Element e, ElementMetadata<?, ?> metadata)
                    throws IOException {
                if (!(e instanceof Link)) {
                    return super.startElement(xw, parent, e, metadata);
                }
                Link link = (Link) e;
                String rel = link.getRel();
                String type = link.getType();
                String href = link.getHref();
                long length = link.getLength();

                if (rel != null && rel.equals("enclosure")) {
                    generateEnclosure(xw, type, href, length);
                } else if ("comments".equals(rel)) {
                    xw.simpleElement(Namespaces.rssNs, "comments", null, href);

                } else if (Rel.ALTERNATE.equals(rel)) {
                    xw.simpleElement(Namespaces.rssNs, "link", null, href);

                } else if (Rel.VIA.equals(rel)) {
                    if (href != null) {
                        List<XmlWriter.Attribute> attrs = Collections
                                .singletonList(new XmlWriter.Attribute("url", href));
                        xw.simpleElement(Namespaces.rssNs, "source", attrs, null);
                    }
                }
                return false;
            }

            @Override
            public void textContent(XmlWriter xw, Element e, ElementMetadata<?, ?> metadata) {
            }

            @Override
            public void endElement(XmlWriter xw, Element e, ElementMetadata<?, ?> metadata) {
            }
        });

        registry.build(Link.KEY, RSS).setProperties(properties);
    }

    private static void addSourceTransforms(MetadataRegistry registry) {
        registry.build(Source.CONSTRUCT, Source.TITLE, RSS).setName(TITLE);

        registry.build(Source.CONSTRUCT, Source.SUBTITLE, RSS).setName(DESCRIPTION);

        XmlWireFormatProperties properties = new XmlWireFormatProperties();
        properties.setElementGenerator(new XmlGenerator.XmlElementGenerator() {
            @Override
            public boolean startElement(XmlWriter xw, Element parent, Element e, ElementMetadata<?, ?> metadata)
                    throws IOException {
                boolean isIcon = e.getElementId().equals(Source.ICON.getId());
                boolean isLogo = e.getElementId().equals(Source.LOGO.getId());

                if ((!isIcon && !isLogo) || !(parent instanceof Source)) {
                    return super.startElement(xw, parent, e, metadata);
                }

                Source source = (Source) parent;

                if (isIcon && source.hasElement(Source.LOGO)) {
                    // atom:logo takes precedence
                    return false;
                }

                xw.startElement(Namespaces.rssNs, "image", null, null);
                xw.simpleElement(Namespaces.rssNs, "url", null, String.valueOf(e.getTextValue()));

                TextContent title = source.getTitle();
                if (title != null) {
                    xw.simpleElement(Namespaces.rssNs, "title", null, title.getPlainText());
                }
                Link htmlLink = source.getHtmlLink();
                if (htmlLink != null) {
                    xw.simpleElement(Namespaces.rssNs, "link", null, htmlLink.getHref());
                }
                xw.endElement(Namespaces.rssNs, "image");

                return false;
            }

            @Override
            public void textContent(XmlWriter xw, Element e, ElementMetadata<?, ?> metadata) {
            }

            @Override
            public void endElement(XmlWriter xw, Element e, ElementMetadata<?, ?> metadata) {
            }
        });
        registry.build(Source.CONSTRUCT, Source.ICON, RSS).setProperties(properties);
        registry.build(Source.CONSTRUCT, Source.LOGO, RSS).setProperties(properties);

        registry.build(Source.CONSTRUCT, Source.RIGHTS, RSS).setVisible(true).setName(COPYRIGHT);

        registry.build(Source.CONSTRUCT, Author.KEY, RSS).setName(MANAGING_EDITOR)
                .setVirtualValue(new MetadataValueTransform(Person.NAME));
    }

    private static void addPersonTransforms(MetadataRegistry registry) {
        registry.build(Person.KEY, Person.EMAIL, RSS).setVisible(false);
        registry.build(Person.KEY, Person.NAME, RSS).setVisible(false);
        registry.build(Person.KEY, Person.URI, RSS).setVisible(false);
    }

    private static void addGeneratorTransforms(MetadataRegistry registry) {
        registry.build(Generator.KEY, RSS).setName(GENERATOR);

        registry.build(Generator.KEY, Generator.URI, RSS).setVisible(false);
        registry.build(Generator.KEY, Generator.VERSION, RSS).setVisible(false);
    }

    private static void addAppEditedTransforms(MetadataRegistry registry) {
        registry.build(Edited.KEY, RSS).setVisible(false);
    }

    private static void generateEnclosure(XmlWriter xw, String type, String href, long length) throws IOException {
        List<XmlWriter.Attribute> attrs = new ArrayList<XmlWriter.Attribute>(3);

        if (type != null) {
            attrs.add(new XmlWriter.Attribute("type", type));
        }

        if (href != null) {
            attrs.add(new XmlWriter.Attribute("url", href));
        }

        // To preserve strict RSS2 compliance and backward compatibility: Since RSS
        // requires a length, then put it length=0 when the length is unknown.  This
        // keeps RSS2 validators happy
        attrs.add(new XmlWriter.Attribute("length", Long.toString(length == -1 ? 0 : length)));

        xw.simpleElement(Namespaces.rssNs, "enclosure", attrs, null);
    }

    private AtomRssTransforms() {
    }
}