org.apache.abdera.ext.json.JSONUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of abdera-extensions-json
Show all versions of abdera-extensions-json
Atom Specification Extensions - JSON
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. 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 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. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package org.apache.abdera.ext.json;
import java.io.IOException;
import java.io.Writer;
import java.util.List;
import javax.xml.namespace.QName;
import org.apache.abdera.Abdera;
import org.apache.abdera.ext.bidi.BidiHelper;
import org.apache.abdera.ext.history.FeedPagingHelper;
import org.apache.abdera.ext.html.HtmlHelper;
import org.apache.abdera.ext.thread.InReplyTo;
import org.apache.abdera.ext.thread.ThreadHelper;
import org.apache.abdera.i18n.iri.IRI;
import org.apache.abdera.i18n.text.Bidi.Direction;
import org.apache.abdera.model.Base;
import org.apache.abdera.model.Categories;
import org.apache.abdera.model.Category;
import org.apache.abdera.model.Collection;
import org.apache.abdera.model.Content;
import org.apache.abdera.model.Control;
import org.apache.abdera.model.Div;
import org.apache.abdera.model.Document;
import org.apache.abdera.model.Element;
import org.apache.abdera.model.Entry;
import org.apache.abdera.model.ExtensibleElement;
import org.apache.abdera.model.Feed;
import org.apache.abdera.model.Generator;
import org.apache.abdera.model.Link;
import org.apache.abdera.model.Person;
import org.apache.abdera.model.Service;
import org.apache.abdera.model.Source;
import org.apache.abdera.model.Text;
import org.apache.abdera.model.TextValue;
import org.apache.abdera.model.Workspace;
import org.apache.abdera.xpath.XPath;
@SuppressWarnings("unchecked")
public class JSONUtil {
public static void toJson(Base base, Writer writer) throws IOException {
JSONStream jstream = new JSONStream(writer);
if (base instanceof Document) {
toJson((Document)base, jstream);
} else if (base instanceof Element) {
toJson((Element)base, jstream);
}
}
private static boolean isSameAsParentBase(Element element) {
IRI parentbase = null;
if (element.getParentElement() != null) {
parentbase =
element instanceof Document ? ((Document)element).getBaseUri() : ((Element)element)
.getResolvedBaseUri();
}
IRI base = element.getResolvedBaseUri();
if (parentbase == null && base != null) {
return false;
}
if (parentbase == null && base == null) {
return true;
}
return parentbase.equals(element.getResolvedBaseUri());
}
private static void toJson(Element element, JSONStream jstream) throws IOException {
if (element instanceof Text) {
Text text = (Text)element;
Text.Type texttype = text.getTextType();
if (texttype.equals(Text.Type.TEXT) && !needToWriteLanguageFields(text)) {
jstream.writeQuoted(text.getValue());
} else {
jstream.startObject();
jstream.writeField("attributes");
jstream.startObject();
jstream.writeField("type", texttype.name().toLowerCase());
writeLanguageFields(element, jstream);
if (!isSameAsParentBase(element)) {
jstream.writeField("xml:base", element.getResolvedBaseUri());
}
jstream.endObject();
jstream.writeField("children");
switch (text.getTextType()) {
case TEXT:
jstream.startArray();
jstream.writeQuoted(text.getValue());
jstream.endArray();
break;
case HTML:
if (text.getValue() != null) {
Div div = HtmlHelper.parse(text.getValue());
writeElementValue(div, jstream);
} else {
jstream.writeQuoted("");
}
break;
case XHTML:
if (text.getValueElement() != null) {
writeElementValue(text.getValueElement(), jstream);
} else {
jstream.writeQuoted("");
}
break;
}
jstream.endObject();
}
} else if (element instanceof Content) {
Content content = (Content)element;
Content.Type contenttype = content.getContentType();
if (contenttype.equals(Content.Type.TEXT) && !needToWriteLanguageFields(content)) {
jstream.writeQuoted(content.getValue());
} else {
jstream.startObject();
jstream.writeField("attributes");
jstream.startObject();
switch (content.getContentType()) {
case TEXT:
case HTML:
case XHTML:
jstream.writeField("type", contenttype.name().toLowerCase());
break;
case MEDIA:
case XML:
jstream.writeField("type", content.getMimeType());
}
writeLanguageFields(element, jstream);
if (!isSameAsParentBase(element))
jstream.writeField("xml:base", element.getResolvedBaseUri());
writeLanguageFields(content, jstream);
jstream.writeField("src", content.getResolvedSrc());
jstream.endObject();
jstream.writeField("children");
switch (content.getContentType()) {
case TEXT:
jstream.startArray();
jstream.writeQuoted(content.getValue());
jstream.endArray();
break;
case HTML:
Div div = HtmlHelper.parse(content.getValue());
writeElementValue(div, jstream);
break;
case XHTML:
writeElementValue(content.getValueElement(), jstream);
break;
case MEDIA:
case XML:
jstream.startArray();
jstream.writeQuoted(content.getValue());
jstream.endArray();
}
jstream.endObject();
}
} else {
if (element instanceof Categories) {
jstream.startObject();
writeLanguageFields(element, jstream);
if (!isSameAsParentBase(element))
jstream.writeField("xml:base", element.getResolvedBaseUri());
Categories categories = (Categories)element;
jstream.writeField("fixed", categories.isFixed() ? "true" : "false");
jstream.writeField("scheme", categories.getScheme());
writeList("categories", categories.getCategories(), jstream);
writeExtensions((ExtensibleElement)element, jstream);
jstream.endObject();
} else if (element instanceof Category) {
jstream.startObject();
writeLanguageFields(element, jstream);
if (!isSameAsParentBase(element))
jstream.writeField("xml:base", element.getResolvedBaseUri());
Category category = (Category)element;
jstream.writeField("term", category.getTerm());
jstream.writeField("scheme", category.getScheme());
jstream.writeField("label", category.getLabel());
writeExtensions((ExtensibleElement)element, jstream);
jstream.endObject();
} else if (element instanceof Collection) {
jstream.startObject();
writeLanguageFields(element, jstream);
if (!isSameAsParentBase(element))
jstream.writeField("xml:base", element.getResolvedBaseUri());
Collection collection = (Collection)element;
jstream.writeField("href", collection.getResolvedHref());
writeElement("title", collection.getTitleElement(), jstream);
String[] accepts = collection.getAccept();
if (accepts != null && accepts.length > 0) {
jstream.writeField("accept");
jstream.startArray();
for (int n = 0; n < accepts.length; n++) {
jstream.writeQuoted(accepts[n]);
if (n < accepts.length - 1)
jstream.writeSeparator();
}
jstream.endArray();
}
List cats = collection.getCategories();
if (cats.size() > 0)
writeList("categories", collection.getCategories(), jstream);
writeExtensions((ExtensibleElement)element, jstream);
jstream.endObject();
} else if (element instanceof Control) {
jstream.startObject();
writeLanguageFields(element, jstream);
if (!isSameAsParentBase(element)) {
jstream.writeField("xml:base", element.getResolvedBaseUri());
}
Control control = (Control)element;
jstream.writeField("draft", control.isDraft() ? "true" : "false");
writeExtensions((ExtensibleElement)element, jstream);
jstream.endObject();
} else if (element instanceof Entry) {
jstream.startObject();
writeLanguageFields(element, jstream);
if (!isSameAsParentBase(element)){
jstream.writeField("xml:base", element.getResolvedBaseUri());
}
Entry entry = (Entry)element;
jstream.writeField("id", entry.getId());
writeElement("title", entry.getTitleElement(), jstream);
writeElement("summary", entry.getSummaryElement(), jstream);
writeElement("rights", entry.getRightsElement(), jstream);
writeElement("content", entry.getContentElement(), jstream);
jstream.writeField("updated", entry.getUpdated());
jstream.writeField("published", entry.getPublished());
jstream.writeField("edited", entry.getEdited());
writeElement("source", entry.getSource(), jstream);
writeList("authors", entry.getAuthors(), jstream);
writeList("contributors", entry.getContributors(), jstream);
writeList("links", entry.getLinks(), jstream);
writeList("categories", entry.getCategories(), jstream);
writeList("inreplyto", ThreadHelper.getInReplyTos(entry), jstream);
writeElement("control", entry.getControl(), jstream);
writeExtensions((ExtensibleElement)element, jstream);
jstream.endObject();
} else if (element instanceof Generator) {
jstream.startObject();
writeLanguageFields(element, jstream);
if (!isSameAsParentBase(element)) {
jstream.writeField("xml:base", element.getResolvedBaseUri());
}
Generator generator = (Generator)element;
jstream.writeField("version", generator.getVersion());
jstream.writeField("uri", generator.getResolvedUri());
jstream.writeField("value", generator.getText());
jstream.endObject();
} else if (element instanceof Link) {
jstream.startObject();
writeLanguageFields(element, jstream);
if (!isSameAsParentBase(element)) {
jstream.writeField("xml:base", element.getResolvedBaseUri());
}
Link link = (Link)element;
jstream.writeField("href", link.getResolvedHref());
jstream.writeField("rel", link.getRel());
jstream.writeField("title", link.getTitle());
jstream.writeField("type", link.getMimeType());
jstream.writeField("hreflang", link.getHrefLang());
if (link.getLength() > -1) {
jstream.writeField("length", link.getLength());
}
writeExtensions((ExtensibleElement)element, jstream);
jstream.endObject();
} else if (element instanceof Person) {
jstream.startObject();
writeLanguageFields(element, jstream);
if (!isSameAsParentBase(element))
jstream.writeField("xml:base", element.getResolvedBaseUri());
Person person = (Person)element;
jstream.writeField("name", person.getName());
if (person.getEmail() != null)
jstream.writeField("email", person.getEmail());
if (person.getUri() != null)
jstream.writeField("uri", person.getUriElement().getResolvedValue());
writeExtensions((ExtensibleElement)element, jstream);
jstream.endObject();
} else if (element instanceof Service) {
jstream.startObject();
writeLanguageFields(element, jstream);
if (!isSameAsParentBase(element))
jstream.writeField("xml:base", element.getResolvedBaseUri());
Service service = (Service)element;
writeList("workspaces", service.getWorkspaces(), jstream);
writeExtensions((ExtensibleElement)element, jstream);
jstream.endObject();
} else if (element instanceof Source) {
jstream.startObject();
writeLanguageFields(element, jstream);
if (!isSameAsParentBase(element))
jstream.writeField("xml:base", element.getResolvedBaseUri());
Source source = (Source)element;
jstream.writeField("id", source.getId());
writeElement("title", source.getTitleElement(), jstream);
writeElement("subtitle", source.getSubtitleElement(), jstream);
writeElement("rights", source.getRightsElement(), jstream);
jstream.writeField("updated", source.getUpdated());
writeElement("generator", source.getGenerator(), jstream);
if (source.getIconElement() != null)
jstream.writeField("icon", source.getIconElement().getResolvedValue());
if (source.getLogoElement() != null)
jstream.writeField("logo", source.getLogoElement().getResolvedValue());
writeList("authors", source.getAuthors(), jstream);
writeList("contributors", source.getContributors(), jstream);
writeList("links", source.getLinks(), jstream);
writeList("categories", source.getCategories(), jstream);
if (FeedPagingHelper.isComplete(source))
jstream.writeField("complete", true);
if (FeedPagingHelper.isArchive(source))
jstream.writeField("archive", true);
if (source instanceof Feed) {
writeList("entries", ((Feed)source).getEntries(), jstream);
}
writeExtensions((ExtensibleElement)element, jstream);
jstream.endObject();
} else if (element instanceof Workspace) {
jstream.startObject();
writeLanguageFields(element, jstream);
if (!isSameAsParentBase(element))
jstream.writeField("xml:base", element.getResolvedBaseUri());
Workspace workspace = (Workspace)element;
writeElement("title", workspace.getTitleElement(), jstream);
writeList("collections", workspace.getCollections(), jstream);
writeExtensions((ExtensibleElement)element, jstream);
jstream.endObject();
} else if (element instanceof InReplyTo) {
jstream.startObject();
writeLanguageFields(element, jstream);
if (!isSameAsParentBase(element))
jstream.writeField("xml:base", element.getResolvedBaseUri());
InReplyTo irt = (InReplyTo)element;
jstream.writeField("ref", irt.getRef());
jstream.writeField("href", irt.getResolvedHref());
jstream.writeField("type", irt.getMimeType());
jstream.writeField("source", irt.getResolvedSource());
jstream.endObject();
} else {
writeElement(element, null, jstream);
}
}
}
private static void writeElementValue(Element element, JSONStream jstream) throws IOException {
writeElementChildren(element, jstream);
}
private static String getName(QName qname) {
String prefix = qname.getPrefix();
String name = qname.getLocalPart();
return (prefix != null && !"".equals(prefix)) ? prefix + ":" + name : name;
}
private static void writeElement(Element child, QName parentqname, JSONStream jstream) throws IOException {
QName childqname = child.getQName();
String prefix = childqname.getPrefix();
jstream.startObject();
jstream.writeField("name", getName(childqname));
jstream.writeField("attributes");
List attributes = child.getAttributes();
jstream.startObject();
if (!isSameNamespace(childqname, parentqname)) {
if (prefix != null && !"".equals(prefix))
jstream.writeField("xmlns:" + prefix);
else
jstream.writeField("xmlns");
jstream.writeQuoted(childqname.getNamespaceURI());
}
if (!isSameAsParentBase(child))
jstream.writeField("xml:base", child.getResolvedBaseUri());
writeLanguageFields(child, jstream);
for (QName attr : attributes) {
String name = getName(attr);
jstream.writeField(name);
if ("".equals(attr.getPrefix()) || "xml".equals(attr.getPrefix())) {
String val = child.getAttributeValue(attr);
if (val != null && ("href".equalsIgnoreCase(name) || "src".equalsIgnoreCase(name) || "action"
.equalsIgnoreCase(name))) {
IRI base = child.getResolvedBaseUri();
if (base != null)
val = base.resolve(val).toASCIIString();
}
jstream.writeQuoted(val);
} else {
jstream.startObject();
jstream.writeField("attributes");
jstream.startObject();
jstream.writeField("xmlns:" + attr.getPrefix());
jstream.writeQuoted(attr.getNamespaceURI());
jstream.endObject();
jstream.writeField("value");
jstream.writeQuoted(child.getAttributeValue(attr));
jstream.endObject();
}
}
jstream.endObject();
jstream.writeField("children");
writeElementChildren((Element)child, jstream);
jstream.endObject();
}
private static void writeElementChildren(Element element, JSONStream jstream) throws IOException {
jstream.startArray();
Object[] children = getChildren(element);
QName parentqname = element.getQName();
for (int n = 0; n < children.length; n++) {
Object child = children[n];
if (child instanceof Element) {
writeElement((Element)child, parentqname, jstream);
if (n < children.length - 1)
jstream.writeSeparator();
} else if (child instanceof TextValue) {
TextValue textvalue = (TextValue)child;
String value = textvalue.getText();
if (!element.getMustPreserveWhitespace()) {
if (!value.matches("\\s*")) {
jstream.writeQuoted(value.trim());
if (n < children.length - 1)
jstream.writeSeparator();
}
} else {
jstream.writeQuoted(value);
if (n < children.length - 1)
jstream.writeSeparator();
}
}
}
jstream.endArray();
}
private static void writeExtensions(ExtensibleElement element, JSONStream jstream) throws IOException {
writeExtensions(element, jstream, true);
}
private static void writeExtensions(ExtensibleElement element, JSONStream jstream, boolean startsep)
throws IOException {
List attributes = element.getExtensionAttributes();
writeList("extensions", element.getExtensions(), jstream);
if (attributes.size() > 0) {
jstream.writeField("attributes");
jstream.startObject();
for (int n = 0; n < attributes.size(); n++) {
QName qname = attributes.get(n);
jstream.writeField(getName(qname));
if ("".equals(qname.getPrefix()) || "xml".equals(qname.getPrefix())) {
jstream.writeQuoted(element.getAttributeValue(qname));
} else {
jstream.startObject();
jstream.writeField("attributes");
jstream.startObject();
jstream.writeField("xmlns:" + qname.getPrefix());
jstream.writeQuoted(qname.getNamespaceURI());
jstream.endObject();
jstream.writeField("value");
jstream.writeQuoted(element.getAttributeValue(qname));
jstream.endObject();
}
}
jstream.endObject();
}
}
private static boolean needToWriteLanguageFields(Element element) {
return needToWriteLang(element) || needToWriteDir(element);
}
private static boolean needToWriteLang(Element element) {
String parentlang = null;
if (element.getParentElement() != null) {
Base parent = element.getParentElement();
parentlang =
parent instanceof Document ? ((Document)parent).getLanguage() : ((Element)parent).getLanguage();
}
String lang = element.getLanguage();
return (parentlang == null && lang != null) || (lang != null && parentlang != null && !parentlang
.equalsIgnoreCase(lang));
}
private static boolean needToWriteDir(Element element) {
Direction parentdir = Direction.UNSPECIFIED;
Direction dir = BidiHelper.getDirection(element);
if (element.getParentElement() != null) {
Base parent = element.getParentElement();
if (parent instanceof Element)
parentdir = BidiHelper.getDirection((Element)parent);
}
return dir != Direction.UNSPECIFIED && !dir.equals(parentdir);
}
private static void writeLanguageFields(Element element, JSONStream jstream) throws IOException {
if (needToWriteLang(element)) {
String lang = element.getLanguage();
jstream.writeField("lang", lang);
}
if (needToWriteDir(element)) {
Direction dir = BidiHelper.getDirection(element);
jstream.writeField("dir", dir.name().toLowerCase());
}
}
private static void writeElement(String name, Element element, JSONStream jstream) throws IOException {
if (element != null) {
jstream.writeField(name);
toJson(element, jstream);
}
}
private static boolean writeList(String name, List list, JSONStream jstream) throws IOException {
if (list == null || list.size() == 0)
return false;
jstream.writeField(name);
jstream.startArray();
for (int n = 0; n < list.size(); n++) {
Element el = (Element)list.get(n);
if (!(el instanceof InReplyTo) && !(el instanceof Control)) {
toJson(el, jstream);
if (n < list.size() - 1)
jstream.writeSeparator();
}
}
jstream.endArray();
return true;
}
private static void toJson(Document document, JSONStream jstream) throws IOException {
jstream.startObject();
jstream.writeField("base", document.getBaseUri());
jstream.writeField("content-type", document.getContentType());
jstream.writeField("etag", document.getEntityTag());
jstream.writeField("language", document.getLanguage());
jstream.writeField("slug", document.getSlug());
jstream.writeField("last-modified", document.getLastModified());
Element root = document.getRoot();
if (root != null) {
String rootname = root.getQName().getLocalPart();
writeElement(rootname, document.getRoot(), jstream);
}
jstream.endObject();
}
private static Object[] getChildren(Element element) {
Abdera abdera = element.getFactory().getAbdera();
XPath xpath = abdera.getXPath();
List