/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
*
* 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 org.apache.streams.rss.serializer;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.rometools.rome.feed.module.Module;
import com.rometools.rome.feed.rss.Enclosure;
import com.rometools.rome.feed.synd.SyndContent;
import com.rometools.rome.feed.synd.SyndEnclosure;
import com.rometools.rome.feed.synd.SyndEntry;
import com.rometools.rome.feed.synd.SyndFeed;
import com.rometools.rome.feed.synd.SyndImage;
import com.rometools.rome.feed.synd.SyndLinkImpl;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import java.util.List;
/**
* Since SyndEntry is not Serializable, we cannot emit them from any StreamOperation. So the CommunityRssProvider
* converts the SyndEntries to ObjectNodes using this class.
*/
public class SyndEntrySerializer {
private static final Logger LOGGER = LoggerFactory.getLogger(SyndEntrySerializer.class);
public ObjectNode deserialize(SyndEntry entry) {
return deserializeRomeEntry(entry);
}
private ObjectNode deserializeRomeEntry(SyndEntry entry) {
JsonNodeFactory factory = JsonNodeFactory.instance;
ObjectNode root = factory.objectNode();
serializeString(entry.getAuthor(), "author", root);
serializeListOfStrings(entry.getAuthors(), "authors", root, factory);
serializeCategories(root, factory, entry.getCategories());
serializeContents(root, factory, entry.getContents());
serializeListOfStrings(entry.getContributors(), "contributors", root, factory);
serializeDescription(root, factory, entry.getDescription());
serializeEnclosures(root, factory, entry.getEnclosures());
serializeForeignMarkUp(root, factory, entry.getForeignMarkup());
serializeString(entry.getLink(), "link", root);
serializeLinks(root, factory, entry.getLinks());
serializeModules(root, factory, entry.getModules());
serializeDate(root, entry.getPublishedDate(), "publishedDate");
serializeSource(root, factory, entry.getSource());
serializeString(entry.getTitle(), "title", root);
serializeDate(root, entry.getUpdatedDate(), "updateDate");
serializeString(entry.getUri(), "uri", root);
return root;
}
private void serializeCategories(ObjectNode root, JsonNodeFactory factory, List categories) {
if (categories == null || categories.size() == 0) {
return;
}
ArrayNode cats = factory.arrayNode();
for (Object obj : categories) {
if (obj instanceof com.rometools.rome.feed.rss.Category) {
ObjectNode catNode = factory.objectNode();
com.rometools.rome.feed.rss.Category category = (com.rometools.rome.feed.rss.Category) obj;
if (category.getDomain() != null) {
catNode.put("domain", category.getDomain());
}
if (category.getValue() != null) {
catNode.put("value", category.getValue());
}
cats.add(catNode);
} else if (obj instanceof com.rometools.rome.feed.atom.Category) {
com.rometools.rome.feed.atom.Category category = (com.rometools.rome.feed.atom.Category) obj;
ObjectNode catNode = factory.objectNode();
if (category.getLabel() != null) {
catNode.put("label", category.getLabel());
}
if (category.getScheme() != null) {
catNode.put("scheme", category.getScheme());
}
if (category.getSchemeResolved() != null) {
catNode.put("schemeResolved", category.getSchemeResolved());
}
if (category.getTerm() != null ) {
catNode.put("term", category.getTerm());
}
cats.add(catNode);
}
}
root.put("categories", cats);
}
private void serializeContents(ObjectNode root, JsonNodeFactory factory, List contents) {
if (contents == null || contents.size() == 0) {
return;
}
ArrayNode contentsArray = factory.arrayNode();
for (Object obj : contents) {
ObjectNode content = factory.objectNode();
if (obj instanceof com.rometools.rome.feed.rss.Content) {
com.rometools.rome.feed.rss.Content rssContent = (com.rometools.rome.feed.rss.Content) obj;
content.put("type", rssContent.getType());
content.put("value", rssContent.getValue());
}
if (obj instanceof com.rometools.rome.feed.atom.Content) {
com.rometools.rome.feed.atom.Content atomContent = (com.rometools.rome.feed.atom.Content) obj;
content.put("type", atomContent.getType());
content.put("value", atomContent.getValue());
content.put("mode", atomContent.getMode());
content.put("src", atomContent.getSrc());
}
contentsArray.add(content);
}
root.put("contents", contentsArray);
}
private void serializeDate(ObjectNode root, Date date, String key) {
DateTimeFormatter formatter = ISODateTimeFormat.dateTime();
if (date == null) {
return;
}
root.put(key, formatter.print(date.getTime()));
}
private void serializeDescription(ObjectNode root, JsonNodeFactory factory, SyndContent synd) {
if (synd == null) {
return;
}
ObjectNode content = factory.objectNode();
if (synd.getValue() != null) {
content.put("value", synd.getValue());
}
if (synd.getMode() != null) {
content.put("mode", synd.getMode());
}
if (synd.getType() != null) {
content.put("type", synd.getType());
}
root.put("description", content);
}
private void serializeEnclosures(ObjectNode root, JsonNodeFactory factory, List enclosures) {
if (enclosures == null || enclosures.size() == 0) {
return;
}
ArrayNode encls = factory.arrayNode();
for (Object obj : enclosures) {
if (obj instanceof Enclosure) {
Enclosure enclosure = (Enclosure) obj;
ObjectNode encl = factory.objectNode();
if (enclosure.getType() != null) {
encl.put("type", enclosure.getType());
}
if (enclosure.getUrl() != null) {
encl.put("url", enclosure.getUrl());
}
encl.put("length", enclosure.getLength());
encls.add(encl);
} else if (obj instanceof SyndEnclosure) {
SyndEnclosure enclosure = (SyndEnclosure) obj;
ObjectNode encl = factory.objectNode();
if (enclosure.getType() != null) {
encl.put("type", enclosure.getType());
}
if (enclosure.getUrl() != null) {
encl.put("url", enclosure.getUrl());
}
encl.put("length", enclosure.getLength());
encls.add(encl);
} else {
LOGGER.warn("serializeEnclosures does not handle type : {}", obj.getClass().toString());
}
}
root.put("enclosures", encls);
}
private void serializeForeignMarkUp(ObjectNode root, JsonNodeFactory factory, Object foreignMarkUp) {
if (foreignMarkUp == null) {
return;
}
if (foreignMarkUp instanceof String) {
root.put("foreignEnclosures", (String) foreignMarkUp);
} else if (foreignMarkUp instanceof List) {
List foreignList = (List) foreignMarkUp;
if (foreignList.size() == 0) {
return;
}
if (foreignList.get(0) instanceof String) {
serializeListOfStrings(foreignList, "foreignEnclosures", root, factory);
} else {
LOGGER.debug("SyndEntry.getForeignMarkUp is not of type String. Need to handle the case of class : {}",
((List)foreignMarkUp).get(0).getClass().toString());
}
} else {
LOGGER.debug("SyndEntry.getForeignMarkUp is not of an expected type. Need to handle the case of class : {}",
foreignMarkUp.getClass().toString());
}
}
private void serializeImage(ObjectNode root, JsonNodeFactory factory, SyndImage image) {
if (image == null) {
return;
}
ObjectNode imageNode = factory.objectNode();
serializeString(image.getDescription(), "description", imageNode);
serializeString(image.getLink(), "link", imageNode);
serializeString(image.getUrl(), "url", imageNode);
serializeString(image.getTitle(), "title", imageNode);
root.put("image", imageNode);
}
private void serializeListOfStrings(List toSerialize, String key, ObjectNode node, JsonNodeFactory factory) {
if (toSerialize == null || toSerialize.size() == 0) {
return;
}
ArrayNode keyNode = factory.arrayNode();
for (Object obj : toSerialize) {
if (obj instanceof String) {
keyNode.add((String) obj);
} else {
LOGGER.debug("Array at Key:{} was expecting item types of String. Received class : {}", key, obj.getClass().toString());
}
}
node.put(key, keyNode);
}
private void serializeLinks(ObjectNode root, JsonNodeFactory factory, List links) {
if( links.size() == 0 ) {
root.put("links", factory.arrayNode());
} else if (links.get(0) instanceof String) {
serializeListOfStrings(links, "links", root, factory);
} else if (links.get(0) instanceof SyndLinkImpl) {
ArrayNode linksArray = factory.arrayNode();
SyndLinkImpl syndLink;
ObjectNode linkNode;
for (Object obj : links) {
linkNode = factory.objectNode();
syndLink = (SyndLinkImpl) obj;
linkNode.put("rel", syndLink.getRel());
linkNode.put("href", syndLink.getHref());
linkNode.put("type", syndLink.getType());
linkNode.put("length", syndLink.getLength());
linkNode.put("hrefLang", syndLink.getHreflang());
linkNode.put("title", syndLink.getTitle());
linksArray.add(linkNode);
}
root.put("links", linksArray);
} else {
LOGGER.error("No implementation for handling links of class : {}", links.get(0).getClass().toString());
}
}
private void serializeModules(ObjectNode root, JsonNodeFactory factory, List modules) {
if (modules == null || modules.size() == 0) {
return;
}
ArrayNode modulesArray = factory.arrayNode();
for (Object obj : modules) {
if (obj instanceof Module) {
Module mod = (Module) obj;
if (mod.getUri() != null) {
modulesArray.add(mod.getUri());
}
} else {
LOGGER.debug("SyndEntry.getModules() items are not of type Module. Need to handle the case of class : {}",
obj.getClass().toString());
}
}
root.put("modules", modulesArray);
}
private void serializeSource(ObjectNode root, JsonNodeFactory factory, SyndFeed source) {
if (source == null) {
return;
}
ObjectNode sourceNode = factory.objectNode();
serializeString(source.getAuthor(), "author", sourceNode);
serializeListOfStrings(source.getAuthors(), "authors", sourceNode, factory);
serializeCategories(sourceNode, factory, source.getCategories());
serializeString(source.getCopyright(), "copyright", sourceNode);
serializeListOfStrings(source.getContributors(), "contributors", sourceNode, factory);
serializeString(source.getDescription(), "description", sourceNode);
serializeDescription(sourceNode, factory, source.getDescriptionEx());
// source.getEntries(); wtf?
serializeString(source.getFeedType(), "feedType", sourceNode);
serializeImage(sourceNode, factory, source.getImage());
serializeForeignMarkUp(sourceNode, factory, source.getForeignMarkup());
serializeString(source.getLanguage(), "language", sourceNode);
serializeString(source.getLink(), "link", sourceNode);
serializeListOfStrings(source.getLinks(), "links", sourceNode, factory);
serializeModules(sourceNode, factory, source.getModules());
serializeDate(sourceNode, source.getPublishedDate(), "publishedDate");
serializeString(source.getTitle(), "title", sourceNode);
serializeString(source.getUri(), "uri", sourceNode);
root.put("source", sourceNode);
}
private void serializeString(String string, String key, ObjectNode node) {
if (string != null && !string.equals("")) {
node.put(key, string);
}
}
}