You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@abdera.apache.org by jm...@apache.org on 2007/09/28 22:40:58 UTC
svn commit: r580481 - in
/incubator/abdera/java/trunk/extensions/json/src/main/java/org/apache/abdera/ext/json:
JSONStream.java JSONUtil.java
Author: jmsnell
Date: Fri Sep 28 13:40:58 2007
New Revision: 580481
URL: http://svn.apache.org/viewvc?rev=580481&view=rev
Log:
Additional refinements on the JSON output based on the feedback from the initial drop. Refactoring
to clean up the code. Pretty printing of the output to make it readable
Added:
incubator/abdera/java/trunk/extensions/json/src/main/java/org/apache/abdera/ext/json/JSONStream.java
Modified:
incubator/abdera/java/trunk/extensions/json/src/main/java/org/apache/abdera/ext/json/JSONUtil.java
Added: incubator/abdera/java/trunk/extensions/json/src/main/java/org/apache/abdera/ext/json/JSONStream.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/extensions/json/src/main/java/org/apache/abdera/ext/json/JSONStream.java?rev=580481&view=auto
==============================================================================
--- incubator/abdera/java/trunk/extensions/json/src/main/java/org/apache/abdera/ext/json/JSONStream.java (added)
+++ incubator/abdera/java/trunk/extensions/json/src/main/java/org/apache/abdera/ext/json/JSONStream.java Fri Sep 28 13:40:58 2007
@@ -0,0 +1,202 @@
+/*
+* 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.Date;
+import java.util.Stack;
+
+import javax.activation.MimeType;
+
+import org.apache.abdera.i18n.iri.IRI;
+import org.apache.abdera.util.EntityTag;
+
+public class JSONStream {
+
+ private final Writer writer;
+ private int depth = 0;
+ private Stack<Boolean> sepstack = new Stack<Boolean>();
+
+ private void pushStack() {
+ sepstack.push(true);
+ }
+
+ private boolean isStart() {
+ boolean b = sepstack.peek();
+ if (b) sepstack.set(sepstack.size()-1, false);
+ return b;
+ }
+
+ private void popStack() {
+ sepstack.pop();
+ }
+
+ public JSONStream(Writer writer) {
+ this.writer = writer;
+ }
+
+ private void inc() {
+ depth++;
+ }
+
+ private void dec() {
+ depth--;
+ }
+
+ private void writeIndent() throws IOException {
+ for (int n = 0; n < depth; n++)
+ writer.write(' ');
+ }
+
+ private void writeNewLine() throws IOException {
+ writer.write('\n');
+ }
+
+ public void startObject() throws IOException {
+ writer.write('{');
+ inc();
+ pushStack();
+ }
+
+ public void endObject() throws IOException {
+ popStack();
+ dec();
+ writeNewLine();
+ writeIndent();
+ writer.write('}');
+ }
+
+ public void startArray() throws IOException {
+ writer.write('[');
+ inc();
+ }
+
+ public void endArray() throws IOException {
+ dec();
+ writeNewLine();
+ writeIndent();
+ writer.write(']');
+ }
+
+ public void writeSeparator() throws IOException {
+ writer.write(',');
+ }
+
+ private void writeColon() throws IOException {
+ writer.write(':');
+ }
+
+ public void writeQuoted(String value) throws IOException {
+ writer.write('"');
+ writer.write(escape(value));
+ writer.write('"');
+ }
+
+ public void writeField(String name) throws IOException {
+ if (!isStart()) writeSeparator();
+ writeNewLine();
+ writeIndent();
+ writeQuoted(name);
+ writeColon();
+ }
+
+
+
+ public void writeField(String name, Date value) throws IOException {
+ if (value != null) writeField(name, value.getTime());
+ }
+
+ public void writeField(String name, IRI value) throws IOException {
+ if (value != null) writeField(name, value.toASCIIString());
+ }
+
+ public void writeField(String name, MimeType value) throws IOException {
+ if (value != null) writeField(name, value.toString());
+ }
+
+ public void writeField(String name, EntityTag value) throws IOException {
+ if (value != null) writeField(name, value.toString());
+ }
+
+ public void writeField(String name, String value) throws IOException {
+ if (value != null) {
+ writeField(name);
+ writeQuoted(value);
+ }
+ }
+
+ public void writeField(String name, Number value) throws IOException {
+ if (value != null) {
+ writeField(name);
+ writer.write(value.toString());
+ }
+ }
+
+ public void writeField(String name, Boolean value) throws IOException {
+ if (value != null) {
+ writeField(name);
+ writer.write(value.toString());
+ }
+ }
+
+ private static String escape(String value) {
+ if (value == null) return null;
+ StringBuffer buf = new StringBuffer();
+ char[] chars = value.toCharArray();
+ char b = 0;
+ String t = null;
+ for (char c : chars) {
+ switch(c) {
+ case '\\':
+ case '"':
+ buf.append('\\');
+ buf.append(c);
+ break;
+ case '/':
+ if (b == '<') buf.append('\\');
+ buf.append(c);
+ break;
+ case '\b':
+ buf.append("\\b");
+ break;
+ case '\t':
+ buf.append("\\t");
+ break;
+ case '\n':
+ buf.append("\\n");
+ break;
+ case '\f':
+ buf.append("\\f");
+ break;
+ case '\r':
+ buf.append("\\r");
+ break;
+ default:
+ if (c < ' ' || c > 127) {
+ t = "000" + Integer.toHexString(c);
+ buf.append("\\u" + t.substring(t.length() - 4));
+ } else {
+ buf.append(c);
+ }
+ }
+ b = c;
+ }
+ return buf.toString();
+ }
+}
Modified: incubator/abdera/java/trunk/extensions/json/src/main/java/org/apache/abdera/ext/json/JSONUtil.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/extensions/json/src/main/java/org/apache/abdera/ext/json/JSONUtil.java?rev=580481&r1=580480&r2=580481&view=diff
==============================================================================
--- incubator/abdera/java/trunk/extensions/json/src/main/java/org/apache/abdera/ext/json/JSONUtil.java (original)
+++ incubator/abdera/java/trunk/extensions/json/src/main/java/org/apache/abdera/ext/json/JSONUtil.java Fri Sep 28 13:40:58 2007
@@ -27,7 +27,7 @@
import org.apache.abdera.ext.history.FeedPagingHelper;
import org.apache.abdera.ext.thread.InReplyTo;
import org.apache.abdera.ext.thread.ThreadHelper;
-import org.apache.abdera.ext.thread.Total;
+import org.apache.abdera.i18n.iri.IRI;
import org.apache.abdera.model.Base;
import org.apache.abdera.model.Categories;
import org.apache.abdera.model.Category;
@@ -55,706 +55,360 @@
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,writer);
+ toJson((Document)base,jstream);
else if (base instanceof Element)
- toJson((Element)base,writer);
+ toJson((Element)base,jstream);
writer.flush();
}
- private static Object[] getChildren(Element element) {
- Abdera abdera = element.getFactory().getAbdera();
- XPath xpath = abdera.getXPath();
- List<Object> nodes = xpath.selectNodes("node()", element);
- return nodes.toArray(new Object[nodes.size()]);
- }
-
- private static void toJson(Element element, Writer writer) throws IOException {
- writer.write('{');
-
+ private static boolean isSameAsParentBase(Element element) {
+ IRI parentbase = null;
+ if (element.getParentElement() != null) {
+ parentbase = element instanceof Document ?
+ ((Document)element).getBaseUri() :
+ ((Element)element).getResolvedBaseUri();
+ }
+ if (parentbase == null && element.getResolvedBaseUri() != null) return false;
+ return parentbase.equals(element.getResolvedBaseUri());
+ }
+
+ private static void toJson(Element element, JSONStream jstream) throws IOException {
+ jstream.startObject();
+
+ writeLanguageFields(element, jstream);
+ if (!isSameAsParentBase(element))
+ jstream.writeField("xml:base", element.getResolvedBaseUri());
+
if (element instanceof Categories) {
Categories categories = (Categories) element;
- writeField("fixed", categories.isFixed()?"true":"false", writer);
- if (categories.getScheme() != null) {
- writer.write(',');
- writeField("scheme", categories.getScheme().toASCIIString(), writer);
- }
- writer.write(',');
- writeList("categories",categories.getCategories(),writer);
-
- writer.write(',');
- writeExtensions((ExtensibleElement)element,writer);
+ jstream.writeField("fixed", categories.isFixed()?"true":"false");
+ jstream.writeField("scheme", categories.getScheme());
+ writeList("categories",categories.getCategories(),jstream);
+ writeExtensions((ExtensibleElement)element,jstream);
} else if (element instanceof Category) {
- Category category = (Category) element;
-
- writeLanguageFields(element, writer);
-
- writeField("term", category.getTerm(), writer);
- if (category.getScheme() != null) {
- writer.write(',');
- writeField("scheme", category.getScheme().toASCIIString(), writer);
- }
- if (category.getLabel() != null) {
- writer.write(',');
- writeField("label", category.getLabel(), writer);
- }
-
- writer.write(',');
- writeExtensions((ExtensibleElement)element,writer);
+ Category category = (Category) element;
+ jstream.writeField("term", category.getTerm());
+ jstream.writeField("scheme", category.getScheme());
+ jstream.writeField("label", category.getLabel());
+ writeExtensions((ExtensibleElement)element,jstream);
} else if (element instanceof Collection) {
Collection collection = (Collection)element;
- if (collection.getResolvedHref() != null) {
- writeField("href", collection.getResolvedHref().toASCIIString(), writer);
- writer.write(',');
- }
- if (collection.getTitleElement() != null) {
- writeElement("title",collection.getTitleElement(),writer);
- writer.write(',');
- }
- writer.write("\"accept\":[");
+ jstream.writeField("href", collection.getResolvedHref());
+ writeElement("title",collection.getTitleElement(),jstream);
String[] accepts = collection.getAccept();
- for (int n = 0; n < accepts.length; n++) {
- writer.write("\"" + escape(accepts[n]) + "\"");
- if (n < accepts.length - 1) writer.write(',');
+ 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();
}
- writer.write("]");
- writer.write(',');
- writeList("categories",collection.getCategories(),writer);
-
- writer.write(',');
- writeExtensions((ExtensibleElement)element,writer);
+ List<Categories> cats = collection.getCategories();
+ if (cats.size() > 0)
+ writeList("categories",collection.getCategories(),jstream);
+ writeExtensions((ExtensibleElement)element,jstream);
} else if (element instanceof Content) {
Content content = (Content)element;
- writeLanguageFields(element, writer);
-
- if (element.getResolvedBaseUri() != null) {
- writeField("base", element.getResolvedBaseUri().toASCIIString(), writer);
- writer.write(',');
- }
- if (content.getResolvedSrc() != null) {
- writeField("src", content.getResolvedSrc().toASCIIString(), writer);
- writer.write(',');
- }
-
+ jstream.writeField("src", content.getResolvedSrc());
switch(content.getContentType()) {
case TEXT:
- writeField("type","text",writer);
- writer.write(',');
- writeField("value",content.getValue(),writer);
+ jstream.writeField("type","text");
+ jstream.writeField("value",content.getValue());
break;
case HTML:
- writeField("type","html",writer);
- writer.write(',');
- writeField("value",content.getValue(),writer);
+ jstream.writeField("type","html");
+ jstream.writeField("value",content.getValue());
break;
case XHTML:
- writeField("type","xhtml",writer);
- writer.write(',');
- writeXHTMLValue((Div)content.getValueElement(), writer);
- writer.write(',');
- writeField("display",content.getValue(), writer);
+ jstream.writeField("type","xhtml");
+ jstream.writeField("value",content.getValue());
+ writeElementValue((Div)content.getValueElement(), jstream);
break;
case MEDIA:
- writeField("type",content.getMimeType().toString(),writer);
- if (content.getSrc() == null) {
- writer.write(',');
- writeField("value",content.getValue(),writer);
- }
- break;
case XML:
- writeField("type",content.getMimeType().toString(),writer);
- if (content.getSrc() == null) {
- writer.write(',');
- writeField("value",content.getValue(),writer);
- }
+ jstream.writeField("type",content.getMimeType());
+ if (content.getSrc() == null)
+ jstream.writeField("value",content.getValue());
break;
}
} else if (element instanceof Control) {
Control control = (Control)element;
- writeField("draft", control.isDraft()?"true":"false",writer);
-
- writer.write(',');
- writeExtensions((ExtensibleElement)element,writer);
+ jstream.writeField("draft", control.isDraft()?"true":"false");
+ writeExtensions((ExtensibleElement)element,jstream);
} else if (element instanceof Entry) {
Entry entry = (Entry)element;
-
- writeField("id", entry.getId().toASCIIString(),writer);
- writer.write(',');
-
- writeElement("title", entry.getTitleElement(),writer);
- writer.write(',');
-
- if (entry.getSummary() != null) {
- writeElement("summary", entry.getSummaryElement(),writer);
- writer.write(',');
- }
-
- if (entry.getRights() != null) {
- writeElement("rights", entry.getRightsElement(),writer);
- writer.write(',');
- }
-
- if (entry.getContentElement() != null) {
- writeElement("content", entry.getContentElement(),writer);
- writer.write(',');
- }
-
- writeField("updated", entry.getUpdated().getTime(),writer);
- writer.write(',');
-
- if (entry.getPublished() != null) {
- writeField("published", entry.getPublished().getTime(),writer);
- writer.write(',');
- }
-
- if (entry.getEdited() != null) {
- writeField("edited", entry.getEdited().getTime(),writer);
- writer.write(',');
- }
-
- if (entry.getSource() != null) {
- writeElement("source", entry.getSource(),writer);
- writer.write(',');
- }
-
- writeList("authors",entry.getAuthors(),writer);
- writer.write(',');
-
- writeList("contributors",entry.getContributors(),writer);
- writer.write(',');
-
- writeList("links",entry.getLinks(),writer);
- writer.write(',');
-
- writeList("categories",entry.getCategories(),writer);
- writer.write(',');
-
- writeList("inreplyto",ThreadHelper.getInReplyTos(entry),writer);
- writer.write(',');
-
- List<Link> links = entry.getLinks("replies");
- writer.write("\"replies\":[");
- Total total = ThreadHelper.getTotal(entry);
- if (total != null) {
- writer.write("\n{");
- writeField("count",total.getValue(),writer);
- writer.write('}');
- if (links.size() > 0) writer.write(',');
- }
- for (int n = 0; n < links.size(); n++) {
- Link link = links.get(n);
- writer.write("\n{");
- writeField("href",link.getResolvedHref().toASCIIString(),writer);
- writer.write(',');
- if (link.getMimeType() != null) {
- writeField("type",link.getMimeType().toString(),writer);
- writer.write(',');
- }
- writeField("count",ThreadHelper.getCount(link),writer);
- writer.write('}');
- if (n < links.size()-1) writer.write(',');
- }
- writer.write("]");
- writer.write(',');
-
- links = entry.getLinks("license");
- writer.write("\"licenses\":[");
- for (int n = 0; n < links.size(); n++) {
- Link link = links.get(n);
- writer.write("\n{");
- writeField("href",link.getResolvedHref().toASCIIString(),writer);
- if (link.getMimeType() != null) {
- writer.write(',');
- writeField("type",link.getMimeType().toString(),writer);
- }
- writer.write('}');
- if (n < links.size()-1) writer.write(',');
- }
- writer.write("]");
-
- writer.write(',');
- writeExtensions((ExtensibleElement)element,writer);
-
+ 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);
+ writeExtensions((ExtensibleElement)element,jstream);
} else if (element instanceof Generator) {
Generator generator = (Generator)element;
-
- writeLanguageFields(element, writer);
-
- if (generator.getVersion() != null) {
- writeField("version", generator.getVersion(), writer);
- }
- if (generator.getResolvedUri() != null) {
- writer.write(',');
- writeField("uri", generator.getResolvedUri().toASCIIString(), writer);
- }
- if (generator.getText() != null) {
- writer.write(',');
- writeField("value", generator.getText(), writer);
- }
+ jstream.writeField("version", generator.getVersion());
+ jstream.writeField("uri", generator.getResolvedUri());
+ jstream.writeField("value", generator.getText());
} else if (element instanceof Link) {
- Link link = (Link)element;
-
- writeLanguageFields(element, writer);
-
- writeField("href", link.getResolvedHref().toASCIIString(), writer);
-
- if (link.getRel() != null) {
- writer.write(',');
- writeField("rel", link.getRel(), writer);
- }
- if (link.getTitle() != null) {
- writer.write(',');
- writeField("title", link.getTitle(), writer);
- }
- if (link.getMimeType() != null) {
- writer.write(',');
- writeField("type", link.getMimeType().toString(), writer);
- }
- if (link.getHrefLang() != null) {
- writer.write(',');
- writeField("hreflang", link.getHrefLang(), writer);
- }
- if (link.getLength() > -1) {
- writer.write(',');
- writeField("length", link.getLength(), writer);
- }
-
- writer.write(',');
- writeExtensions((ExtensibleElement)element,writer);
+ 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);
} else if (element instanceof Person) {
- Person person = (Person)element;
-
- writeLanguageFields(element, writer);
-
- writeField("name",person.getName(),writer);
- writer.write(',');
- writeField("email",person.getEmail(),writer);
- writer.write(',');
- if (person.getUriElement() != null)
- writeField("uri",person.getUriElement().getResolvedValue().toASCIIString(),writer);
-
- writer.write(',');
- writeExtensions((ExtensibleElement)element,writer);
+ Person person = (Person)element;
+ jstream.writeField("name",person.getName());
+ jstream.writeField("email",person.getEmail());
+ jstream.writeField("uri",person.getUriElement().getResolvedValue());
+ writeExtensions((ExtensibleElement)element,jstream);
} else if (element instanceof Service) {
Service service = (Service)element;
- writeList("workspaces",service.getWorkspaces(),writer);
-
- writer.write(',');
- writeExtensions((ExtensibleElement)element,writer);
+ writeList("workspaces",service.getWorkspaces(),jstream);
+ writeExtensions((ExtensibleElement)element,jstream);
} else if (element instanceof Source) {
Source source = (Source)element;
-
- writeField("id", source.getId().toASCIIString(),writer);
- writer.write(',');
-
- writeElement("title", source.getTitleElement(),writer);
- writer.write(',');
-
- if (source.getSubtitle() != null) {
- writeElement("subtitle", source.getSubtitleElement(),writer);
- writer.write(',');
- }
-
- if (source.getRights() != null) {
- writeElement("rights", source.getRightsElement(),writer);
- writer.write(',');
- }
-
- writeField("updated", source.getUpdated().getTime(),writer);
- writer.write(',');
-
- if (source.getGenerator() != null) {
- writeElement("generator", source.getGenerator(),writer);
- writer.write(',');
- }
-
- if (source.getIconElement() != null) {
- writeField("icon", source.getIconElement().getResolvedValue().toASCIIString(),writer);
- writer.write(',');
- }
-
- if (source.getLogoElement() != null) {
- writeField("logo", source.getLogoElement().getResolvedValue().toASCIIString(),writer);
- writer.write(',');
- }
-
- writeList("authors",source.getAuthors(),writer);
- writer.write(',');
-
- writeList("contributors",source.getContributors(),writer);
- writer.write(',');
-
- writeList("links",source.getLinks(),writer);
- writer.write(',');
-
- writeList("categories",source.getCategories(),writer);
- writer.write(',');
-
- writeField("complete",FeedPagingHelper.isComplete(source), writer);
- writer.write(',');
-
- writeField("archive",FeedPagingHelper.isArchive(source), writer);
-
+ 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);
+ jstream.writeField("icon", source.getIconElement().getResolvedValue());
+ 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) {
- writer.write(',');
- writeList("entries",((Feed)source).getEntries(),writer);
+ writeList("entries",((Feed)source).getEntries(),jstream);
}
-
- writer.write(',');
- writeExtensions((ExtensibleElement)element,writer);
-
+ writeExtensions((ExtensibleElement)element,jstream);
} else if (element instanceof Text) {
- Text text = (Text)element;
-
- writeLanguageFields(element, writer);
-
- if (element.getResolvedBaseUri() != null) {
- writeField("base", element.getResolvedBaseUri().toASCIIString(), writer);
- writer.write(',');
- }
-
+ Text text = (Text)element;
switch(text.getTextType()) {
case TEXT:
- writeField("type","text",writer);
- writer.write(',');
- writeField("value",text.getValue(),writer);
+ jstream.writeField("type","text");
+ jstream.writeField("value",text.getValue());
break;
case HTML:
- writeField("type","html",writer);
- writer.write(',');
- writeField("value",text.getValue(),writer);
+ jstream.writeField("type","html");
+ jstream.writeField("value",text.getValue());
break;
case XHTML:
- writeField("type","xhtml",writer);
- writer.write(',');
- writeXHTMLValue(text.getValueElement(), writer);
- writer.write(',');
- writeField("display",text.getValue(), writer);
+ jstream.writeField("type","xhtml");
+ jstream.writeField("value",text.getValue());
+ writeElementValue(text.getValueElement(), jstream);
break;
}
} else if (element instanceof Workspace) {
Workspace workspace = (Workspace)element;
-
- writeElement("title",workspace.getTitleElement(),writer);
- writer.write(',');
- writeList("collections",workspace.getCollections(),writer);
-
- writer.write(',');
- writeExtensions((ExtensibleElement)element,writer);
+ writeElement("title",workspace.getTitleElement(),jstream);
+ writeList("collections",workspace.getCollections(),jstream);
+ writeExtensions((ExtensibleElement)element,jstream);
} else if (element instanceof InReplyTo) {
- InReplyTo irt = (InReplyTo)element;
-
- writeField("ref",irt.getRef().toASCIIString(),writer);
-
- if (irt.getHref() != null) {
- writer.write(',');
- writeField("href",irt.getResolvedHref().toASCIIString(),writer);
- }
-
- if (irt.getMimeType() != null) {
- writer.write(',');
- writeField("type",irt.getMimeType().toString(),writer);
- }
-
- if (irt.getSource() != null) {
- writer.write(',');
- writeField("source",irt.getResolvedSource().toASCIIString(),writer);
- }
-
+ InReplyTo irt = (InReplyTo)element;
+ jstream.writeField("ref",irt.getRef());
+ jstream.writeField("href",irt.getResolvedHref());
+ jstream.writeField("type",irt.getMimeType());
+ jstream.writeField("source",irt.getResolvedSource());
} else {
- writeQName(element.getQName(),writer);
- writer.write(',');
- writeLanguageFields(element, writer);
-
- if (element.getResolvedBaseUri() != null) {
- writeField("base", element.getResolvedBaseUri().toASCIIString(), writer);
- writer.write(',');
- }
- writer.write("\"attributes\":");
- writer.write('[');
- List<QName> attributes = element.getAttributes();
- for (int n = 0; n < attributes.size(); n++) {
- QName qname = attributes.get(n);
- writeAttribute(qname, element.getAttributeValue(qname), writer);
- if (n < attributes.size()-1) writer.write(',');
- }
- writer.write(']');
- writer.write(',');
- writer.write("\"children\":");
- writeChildren(element, writer);
+ writeElement(element,null,jstream);
}
- writer.write('}');
+ jstream.endObject();
}
- private static void writeXHTMLValue(Div div, Writer writer) throws IOException {
- writer.write("\n\"value\":");
- writeXHTMLChildren(div, writer);
+ private static void writeElementValue(Element element, JSONStream jstream) throws IOException {
+ jstream.writeField("valuehash");
+ writeElementChildren(element, jstream);
}
- private static void writeXHTMLChildren(Element element, Writer writer) throws IOException {
- writer.write('[');
- Object[] children = getChildren(element);
- for (int n = 0; n < children.length; n++) {
- Object child = children[n];
- if (child instanceof Element) {
- Element childel = (Element) child;
- QName childqname = childel.getQName();
- writer.write("[\n");
- if (childqname.getNamespaceURI() != null && childqname.getNamespaceURI().equals(Constants.XHTML_NS)) {
- writer.write('"');
- writer.write(escape(childqname.getLocalPart()));
- writer.write('"');
- } else {
- writeQName(childqname,writer,false);
- }
- writer.write(',');
- List<QName> attributes = childel.getAttributes();
- writer.write('{');
- for (int i = 0; i < attributes.size(); i++) {
- QName attr = attributes.get(i);
- writer.write('"');
- writer.write(escape(attr.getLocalPart()));
- writer.write('"');
- writer.write(':');
- writer.write('"');
- writer.write(escape(childel.getAttributeValue(attr)));
- writer.write('"');
- if (i < attributes.size()-1) writer.write(',');
- }
- writer.write('}');
- writer.write(',');
- writeXHTMLChildren((Element)child,writer);
- writer.write("]\n");
- } else if (child instanceof TextValue) {
- TextValue textvalue = (TextValue) child;
- writer.write("\"" + escape(textvalue.getText()) + "\"");
- }
- if (n < children.length-1) writer.write(',');
- }
- writer.write(']');
+ private static void writeElement(Element child, QName parentqname, JSONStream jstream) throws IOException {
+ QName childqname = child.getQName();
+ String prefix = childqname.getPrefix();
+ String uri = childqname.getNamespaceURI();
+ jstream.startArray();
+
+ if (prefix != null && !"".equals(prefix)) {
+ jstream.writeQuoted(childqname.getPrefix() + ":" + childqname.getLocalPart());
+ } else {
+ jstream.writeQuoted(childqname.getLocalPart());
+ }
+ jstream.writeSeparator();
+ List<QName> attributes = child.getAttributes();
+ jstream.startObject();
+ if (!Constants.XHTML_NS.equals(uri) && !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) {
+ jstream.writeField(attr.getLocalPart(),child.getAttributeValue(attr));
+ }
+ jstream.endObject();
+ jstream.writeSeparator();
+ writeElementChildren((Element)child,jstream);
+ jstream.endArray();
}
- private static void writeChildren(Element element, Writer writer) throws IOException {
- writer.write('[');
+ 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) {
- toJson((Element)child, writer);
+ writeElement((Element)child, parentqname, jstream);
+ if (n < children.length-1) jstream.writeSeparator();
} else if (child instanceof TextValue) {
TextValue textvalue = (TextValue) child;
- writer.write("\"" + escape(textvalue.getText()) + "\"");
+ 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();
+ }
}
- if (n < children.length-1) writer.write(',');
}
- writer.write(']');
+ jstream.endArray();
}
- private static void writeExtensions(ExtensibleElement element, Writer writer) throws IOException {
- writeList("extensions",element.getExtensions(),writer);
- writer.write(',');
- writer.write("\"attributes\":");
- writer.write('[');
+ 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<QName> attributes = element.getExtensionAttributes();
- for (int n = 0; n < attributes.size(); n++) {
- QName qname = attributes.get(n);
- writeAttribute(qname, element.getAttributeValue(qname), writer);
- if (n < attributes.size()-1) writer.write(',');
+ writeList("extensions",element.getExtensions(),jstream);
+ if (attributes.size() > 0) {
+ jstream.writeField("attributes");
+ jstream.startArray();
+ for (int n = 0; n < attributes.size(); n++) {
+ QName qname = attributes.get(n);
+ writeAttribute(qname, element.getAttributeValue(qname), jstream);
+ if (n < attributes.size()-1) jstream.writeSeparator();
+ }
+ jstream.endArray();
}
- writer.write(']');
}
- private static void writeLanguageFields(Element element, Writer writer) throws IOException {
+ private static void writeLanguageFields(Element element, JSONStream jstream) throws IOException {
+ String parentlang = null;
+ BidiHelper.Direction parentdir = BidiHelper.Direction.UNSPECIFIED;
+ if (element.getParentElement() != null) {
+ Base parent = element.getParentElement();
+ parentlang = parent instanceof Document ?
+ ((Document)parent).getLanguage() :
+ ((Element)parent).getLanguage();
+ if (parent instanceof Element) {
+ parentdir = BidiHelper.getDirection((Element)parent);
+ }
+ }
String lang = element.getLanguage();
- boolean whitespace = element.getMustPreserveWhitespace();
BidiHelper.Direction dir = BidiHelper.getDirection(element);
- if (lang != null) {
- writeField("language",lang,writer);
- }
-
- if (!whitespace) {
- if (lang != null) writer.write(',');
- writeField("whitespace", "false", writer);
- }
-
- if (dir != null && dir != BidiHelper.Direction.UNSPECIFIED) {
- if (lang != null || !whitespace) writer.write(',');
- writeField("dir", dir.name().toLowerCase(), writer);
+ if (parentlang == null || (parentlang != null && !parentlang.equalsIgnoreCase(lang)))
+
+ jstream.writeField("xml:lang",lang);
+ if (dir != null && dir != BidiHelper.Direction.UNSPECIFIED && !dir.equals(parentdir)) {
+ jstream.writeField("dir", dir.name().toLowerCase());
}
-
- if (lang != null ||
- !whitespace ||
- (dir != null && dir != BidiHelper.Direction.UNSPECIFIED))
- writer.write(',');
}
- private static void writeElement(String name, Element element, Writer writer) throws IOException {
+ private static void writeElement(String name, Element element, JSONStream jstream) throws IOException {
if (element != null) {
- writer.write("\n\"" + escape(name) + "\":");
- toJson(element,writer);
+ jstream.writeField(name);
+ toJson(element,jstream);
}
}
- private static void writeList(String name, List list, Writer writer) throws IOException {
- writer.write("\n\"" + escape(name) + "\":[");
+ 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++) {
- toJson((Element)list.get(n),writer);
- if (n < list.size()-1) writer.write(",\n");
+ toJson((Element)list.get(n),jstream);
+ if (n < list.size()-1) jstream.writeSeparator();
}
- writer.write("]");
+ jstream.endArray();
+ return true;
}
- private static void toJson(Document document, Writer writer) throws IOException {
- writer.write('{');
-
- if (document.getBaseUri() != null) {
- writeField("base", document.getBaseUri().toASCIIString(), writer);
- writer.write(',');
- }
-
- if (document.getCharset() != null) {
- writeField("charset", document.getCharset(), writer);
- writer.write(',');
- }
-
- if (document.getContentType() != null) {
- writeField("contenttype", document.getContentType().toString(), writer);
- writer.write(',');
- }
-
- if (document.getEntityTag() != null) {
- writeField("etag", document.getEntityTag().toString(), writer);
- writer.write(',');
- }
-
- if (document.getLanguage() != null) {
- writeField("language", document.getLanguage().toString(), writer);
- writer.write(',');
- }
-
- if (document.getSlug() != null) {
- writeField("slug", document.getSlug(), writer);
- writer.write(',');
- }
-
- if (document.getLastModified() != null) {
- writeField("lastmodified", document.getLastModified().getTime(), writer);
- writer.write(',');
- }
-
- if (!document.getMustPreserveWhitespace()) {
- writeField("whitespace", "false", writer);
- writer.write(',');
- }
-
- Element root = document.getRoot();
- if (root != null) {
- writer.write("\n\"root\":");
- toJson(root,writer);
+ private static void toJson(Document document, JSONStream jstream) throws IOException {
+ jstream.startObject();
+ jstream.writeField("base", document.getBaseUri());
+ jstream.writeField("charset", document.getCharset());
+ jstream.writeField("contenttype", document.getContentType());
+ jstream.writeField("etag", document.getEntityTag());
+ jstream.writeField("language", document.getLanguage());
+ jstream.writeField("slug", document.getSlug());
+ jstream.writeField("lastmodified", document.getLastModified());
+ jstream.writeField("whitespace", "false");
+ writeElement("root",document.getRoot(),jstream);
+ jstream.endObject();
+ }
+
+ private static void writeAttribute(QName qname, String value, JSONStream jstream) throws IOException {
+ jstream.startArray();
+ String prefix = qname.getPrefix();
+ String localpart = qname.getLocalPart();
+ String uri = qname.getNamespaceURI();
+ if (prefix != null && !"".equals(prefix)) {
+ jstream.writeQuoted(prefix + ":" + localpart);
+ jstream.writeSeparator();
+ jstream.startObject();
+ jstream.writeField("xmlns:" + prefix, uri);
+ jstream.endObject();
} else {
- writer.write("\"root\":null");
+ jstream.writeQuoted(localpart);
}
-
- writer.write('}');
+ jstream.writeSeparator();
+ jstream.writeQuoted(value);
+ jstream.endArray();
+ }
+
+ private static Object[] getChildren(Element element) {
+ Abdera abdera = element.getFactory().getAbdera();
+ XPath xpath = abdera.getXPath();
+ List<Object> nodes = xpath.selectNodes("node()", element);
+ return nodes.toArray(new Object[nodes.size()]);
+ }
+
+ private static boolean isSameNamespace(QName q1, QName q2) {
+ if (q1 == null && q2 != null) return false;
+ if (q1 != null && q2 == null) return false;
+ String p1 = q1 == null ? "" : q1.getPrefix() != null ? q1.getPrefix() : "";
+ String p2 = q2 == null ? "" : q2.getPrefix() != null ? q2.getPrefix() : "";
+ String n1 = q1 == null ? "" : q1.getNamespaceURI() != null ? q1.getNamespaceURI() : "";
+ String n2 = q2 == null ? "" : q2.getNamespaceURI() != null ? q2.getNamespaceURI() : "";
+ return n1.equals(n2) && p1.equals(p2);
}
-
- private static void writeField(String name, boolean value, Writer writer) throws IOException {
- writer.write("\n\"");
- writer.write(escape(name));
- writer.write('"');
- writer.write(':');
- writer.write(value?"true":"false");
- }
-
- private static void writeField(String name, String value, Writer writer) throws IOException {
- if (value == null) return;
- writer.write("\n\"");
- writer.write(escape(name));
- writer.write('"');
- writer.write(':');
- writer.write('"');
- writer.write(escape(value));
- writer.write('"');
- }
-
- private static void writeField(String name, Number value, Writer writer) throws IOException {
- if (value == null) return;
- writer.write("\n\"");
- writer.write(escape(name));
- writer.write('"');
- writer.write(':');
- writer.write(value.toString());
- }
-
- private static void writeQName(QName qname, Writer writer) throws IOException {
- writeQName(qname,writer,true);
- }
-
- private static void writeQName(QName qname, Writer writer, boolean includefieldname) throws IOException {
- if (includefieldname) writer.write("\n\"qname\":");
- writer.write('{');
- writeField("name",escape(qname.getLocalPart()),writer);
- if (qname.getNamespaceURI() != null) {
- writer.write(',');
- writeField("ns",escape(qname.getNamespaceURI()),writer);
- }
- if (qname.getPrefix() != null) {
- writer.write(',');
- writeField("prefix",escape(qname.getPrefix()),writer);
- }
- writer.write('}');
- }
-
- private static void writeAttribute(QName qname, String value, Writer writer) throws IOException {
- writer.write("\n{");
- writeQName(qname,writer);
- writer.write(',');
- writeField("value",escape(value),writer);
- writer.write('}');
- }
-
- private static String escape(String value) {
- StringBuffer buf = new StringBuffer();
- char[] chars = value.toCharArray();
- char b = 0;
- String t = null;
- for (char c : chars) {
- switch(c) {
- case '\\':
- case '"':
- buf.append('\\');
- buf.append(c);
- break;
- case '/':
- if (b == '<') buf.append('\\');
- buf.append(c);
- break;
- case '\b':
- buf.append("\\b");
- break;
- case '\t':
- buf.append("\\t");
- break;
- case '\n':
- buf.append("\\n");
- break;
- case '\f':
- buf.append("\\f");
- break;
- case '\r':
- buf.append("\\r");
- break;
- default:
- if (c < ' ' || c > 127) {
- t = "000" + Integer.toHexString(c);
- buf.append("\\u" + t.substring(t.length() - 4));
- } else {
- buf.append(c);
- }
- }
- b = c;
- }
- return buf.toString();
- }
}