abdera-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jmsn...@apache.org
Subject svn commit: r1173209 [31/49] - in /abdera/abdera2: ./ .settings/ activities/ activities/src/ activities/src/main/ activities/src/main/java/ activities/src/main/java/org/ activities/src/main/java/org/apache/ activities/src/main/java/org/apache/abdera2/ ...
Date Tue, 20 Sep 2011 15:57:20 GMT
Added: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/history/FeedPagingHelper.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/history/FeedPagingHelper.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/history/FeedPagingHelper.java (added)
+++ abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/history/FeedPagingHelper.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,258 @@
+/*
+ * 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.abdera2.ext.history;
+
+import javax.xml.namespace.QName;
+
+import static org.apache.abdera2.model.Link.REL_NEXT;
+import static org.apache.abdera2.model.Link.REL_PREV;
+import static org.apache.abdera2.model.Link.REL_CURRENT;
+import static org.apache.abdera2.model.Link.REL_PREVIOUS;
+import static org.apache.abdera2.model.Link.REL_FIRST;
+import static org.apache.abdera2.model.Link.REL_LAST;
+import static org.apache.abdera2.model.Link.REL_NEXT_ARCHIVE;
+import static org.apache.abdera2.model.Link.REL_PREV_ARCHIVE;
+
+import org.apache.abdera2.common.iri.IRI;
+import org.apache.abdera2.model.ExtensibleElement;
+import org.apache.abdera2.model.Link;
+import org.apache.abdera2.model.Source;
+
+/**
+ * Initial support for Mark Nottingham's Feed Paging and Archiving draft
+ * (http://ietfreport.isoc.org/all-ids/draft-nottingham-atompub-feed-history-11.txt)
+ */
+@SuppressWarnings("deprecation")
+public final class FeedPagingHelper {
+
+    public static final String FH_PREFIX = "fh";
+    public static final String FHNS = "http://purl.org/syndication/history/1.0";
+    public static final QName COMPLETE = new QName(FHNS, "complete", FH_PREFIX);
+    public static final QName ARCHIVE = new QName(FHNS, "archive", FH_PREFIX);
+
+    FeedPagingHelper() {
+    }
+
+    /**
+     * Returns true if the feed is "complete". According to the Feed Paging and Archiving specification, in a complete
+     * feed, "any entry not actually in the feed document SHOULD NOT be considered to be part of that feed."
+     * 
+     * @param feed The feed to check
+     */
+    public static boolean isComplete(Source feed) {
+        return feed.has(COMPLETE);
+    }
+
+    /**
+     * Flag the feed as being complete. According to the Feed Paging and Archiving specification, in a complete feed,
+     * "any entry not actually in the feed document SHOULD NOT be considered to be part of that feed."
+     * 
+     * @param feed The Feed to mark as complete
+     * @param complete True if the feed is complete
+     */
+    public static void setComplete(Source feed, boolean complete) {
+      toggle(complete,feed,COMPLETE);
+    }
+
+    /**
+     * Flag the feed as being an archive.
+     * 
+     * @param feed The Feed to mark as an archive
+     * @param archive True if the feed is an archive
+     */
+    public static void setArchive(Source feed, boolean archive) {
+      toggle(archive,feed,ARCHIVE);
+    }
+    
+    private static void toggle(
+      boolean val, 
+      ExtensibleElement el, 
+      QName qname) {
+      if (val)
+          if (!el.has(qname))
+              el.addExtension(qname);
+      else
+          if (el.has(qname))
+              el.getExtension(qname).discard();
+  }
+
+    /**
+     * Return true if the feed has been marked as an archive
+     * 
+     * @param feed The feed to check
+     */
+    public static boolean isArchive(Source feed) {
+        return feed.has(ARCHIVE);
+    }
+
+    /**
+     * Return true if the feed contains any next, previous, first or last paging link relations
+     * 
+     * @param feed The feed to check
+     */
+    public static boolean isPaged(Source feed) {
+        return feed.getLink(REL_NEXT) != null 
+            || feed.getLink(REL_PREVIOUS) != null
+            || feed.getLink(REL_PREV) != null
+            || feed.getLink(REL_FIRST) != null
+            || feed.getLink(REL_LAST) != null;
+    }
+
+    private static Link _setLink(Source feed, String rel, String iri) {
+      Link link = feed.getLink(rel);
+      if (link != null)
+          link.setHref(iri);
+      else
+          link = feed.addLink(iri, rel);
+      return link;
+  }
+    
+    /**
+     * Adds a next link relation to the feed
+     * 
+     * @param feed The feed
+     * @param iri The IRI of the next feed document
+     * @return The newly created Link
+     */
+    public static Link setNext(Source feed, String iri) {
+        return _setLink(feed, REL_NEXT, iri);
+    }
+
+    /**
+     * Adds a previous link relation to the feed
+     * 
+     * @param feed The feed
+     * @param iri The IRI of the previous feed document
+     * @return The newly created Link
+     */
+    public static Link setPrevious(Source feed, String iri) {
+      return _setLink(feed, REL_PREVIOUS, iri);
+    }
+
+    /**
+     * Adds a first link relation to the feed
+     * 
+     * @param feed The feed
+     * @param iri The IRI of the first feed document
+     * @return The newly created Link
+     */
+    public static Link setFirst(Source feed, String iri) {
+      return _setLink(feed, REL_FIRST, iri);
+    }
+
+    /**
+     * Adds a last link relation to the feed
+     * 
+     * @param feed The feed
+     * @param iri The IRI of the last feed document
+     * @return The newly created Link
+     */
+    public static Link setLast(Source feed, String iri) {
+      return _setLink(feed, REL_LAST, iri);
+    }
+
+    /**
+     * Adds a next-archive link relation to the feed
+     * 
+     * @param feed The feed
+     * @param iri The IRI of the next archive feed document
+     * @return The newly created Link
+     */
+    public static Link setNextArchive(Source feed, String iri) {
+      return _setLink(feed, REL_NEXT_ARCHIVE, iri);
+    }
+
+    /**
+     * Adds a prev-archive link relation to the feed
+     * 
+     * @param feed The feed
+     * @param iri The IRI of the previous archive feed document
+     * @return The newly created Link
+     */
+    public static Link setPreviousArchive(Source feed, String iri) {
+      return _setLink(feed, REL_PREV_ARCHIVE, iri);
+    }
+
+    /**
+     * Adds a current link relation to the feed
+     * 
+     * @param feed The feed
+     * @param iri The IRI of the current feed document
+     * @return The newly created Link
+     */
+    public static Link setCurrent(Source feed, String iri) {
+      return _setLink(feed, REL_CURRENT, iri);
+    }
+
+    private static IRI _getLink(Source feed, String rel) {
+      Link link = feed.getLink(rel);
+      return (link != null) ? link.getResolvedHref() : null;
+    }
+    
+    /**
+     * Returns the IRI of the next link relation
+     */
+    public static IRI getNext(Source feed) {
+        return _getLink(feed, REL_NEXT);
+    }
+
+    /**
+     * Returns the IRI of the previous link relation
+     */
+    public static IRI getPrevious(Source feed) {
+        IRI iri = _getLink(feed, REL_PREVIOUS);
+        if (iri == null)
+          iri = _getLink(feed, REL_PREV);
+        return iri;
+    }
+
+    /**
+     * Returns the IRI of the first link relation
+     */
+    public static IRI getFirst(Source feed) {
+        return _getLink(feed, REL_FIRST);
+    }
+
+    /**
+     * Returns the IRI of the last link relation
+     */
+    public static IRI getLast(Source feed) {
+        return _getLink(feed, REL_LAST);
+    }
+
+    /**
+     * Returns the IRI of the prev-archive link relation
+     */
+    public static IRI getPreviousArchive(Source feed) {
+        return _getLink(feed,REL_PREV_ARCHIVE);
+    }
+
+    /**
+     * Returns the IRI of the next-archive link relation
+     */
+    public static IRI getNextArchive(Source feed) {
+        return _getLink(feed,REL_NEXT_ARCHIVE);
+    }
+
+    /**
+     * Returns the IRI of the current link relation
+     */
+    public static IRI getCurrent(Source feed) {
+        return _getLink(feed,REL_CURRENT);
+    }
+}

Propchange: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/history/FeedPagingHelper.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/html/HtmlCleaner.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/html/HtmlCleaner.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/html/HtmlCleaner.java (added)
+++ abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/html/HtmlCleaner.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,141 @@
+/*
+ * 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.abdera2.ext.html;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.Writer;
+import java.util.Arrays;
+
+import nu.validator.htmlparser.sax.HtmlSerializer;
+
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+public class HtmlCleaner {
+
+    private HtmlCleaner() {
+    }
+
+    public static String parse(String value) {
+        return parse(new StringReader(value), true);
+    }
+
+    public static String parse(InputStream in) {
+        return parse(in, "UTF-8");
+    }
+
+    public static String parse(InputStream in, String charset) {
+        try {
+            return parse(new InputStreamReader(in, charset), true);
+        } catch (RuntimeException e) {
+            throw e;
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static String parse(Reader in, boolean fragment) {
+        try {
+            nu.validator.htmlparser.sax.HtmlParser htmlParser = 
+              new nu.validator.htmlparser.sax.HtmlParser();
+            htmlParser.setMappingLangToXmlLang(true);
+            htmlParser.setReportingDoctype(false);
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            Writer w = new OutputStreamWriter(out, "UTF-8");
+            HtmlSerializer ser = new VoidElementFixHtmlSerializer(w);
+            htmlParser.setContentHandler(ser);
+            htmlParser.setLexicalHandler(ser);
+            if (!fragment)
+                htmlParser.parse(new InputSource(in));
+            else
+                htmlParser.parseFragment(new InputSource(in), "div");
+            try {
+                w.flush();
+            } catch (IOException e) {
+            }
+            return new String(out.toByteArray(), "UTF-8");
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
+    private static class VoidElementFixHtmlSerializer extends HtmlSerializer {
+        private static final String[] VOID_ELEMENTS =
+            {"area", "base", "basefont", "bgsound", "br", "col", "embed", "frame", "hr", "img", "input", "link",
+             "meta", "param", "spacer", "wbr"};
+        private final Writer writer;
+
+        public VoidElementFixHtmlSerializer(Writer out) {
+            super(out);
+            this.writer = out;
+        }
+
+        @Override
+        public void endElement(String uri, String localName, String name) throws SAXException {
+            if (Arrays.binarySearch(VOID_ELEMENTS, localName) > -1) {
+                try {
+                    writer.write('<');
+                    writer.write('/');
+                    writer.write(localName);
+                    writer.write('>');
+                } catch (IOException e) {
+                    throw new SAXException(e);
+                }
+            }
+            super.endElement(uri, localName, name);
+        }
+
+        @Override
+        public void characters(char[] ch, int start, int length) throws SAXException {
+            StringBuilder buf = new StringBuilder();
+            for (int n = start; n < (start + length); n++) {
+                if (ch[n] == '<')
+                    buf.append("&lt;");
+                else if (ch[n] == '>')
+                    buf.append("&gt;");
+                else if (ch[n] == '&') {
+                    boolean isentity = false;
+                    int i = n;
+                    String ent = null;
+                    for (; i < (start + length); i++) {
+                        if (ch[i] == ';') {
+                            ent = new String(ch, n, i - n + 1);
+                            isentity = ent.matches("\\&[\\w]*\\;");
+                            break;
+                        }
+                    }
+                    if (isentity) {
+                        buf.append(ent);
+                        n = i;
+                    } else {
+                        buf.append("&amp;");
+                    }
+                } else
+                    buf.append(ch[n]);
+            }
+            super.characters(buf.toString().toCharArray(), 0, buf.length());
+        }
+    }
+}

Propchange: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/html/HtmlCleaner.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/html/HtmlHelper.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/html/HtmlHelper.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/html/HtmlHelper.java (added)
+++ abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/html/HtmlHelper.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,160 @@
+/*
+ * 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.abdera2.ext.html;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.Arrays;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.apache.abdera2.Abdera;
+import org.apache.abdera2.model.Div;
+import org.apache.abdera2.model.Document;
+import org.apache.abdera2.model.Element;
+import org.apache.abdera2.protocol.client.BasicClient;
+import org.apache.abdera2.protocol.client.ClientResponse;
+import org.apache.abdera2.protocol.client.Client;
+import org.apache.abdera2.protocol.client.Session;
+import org.apache.abdera2.common.mediatype.MimeTypeHelper;
+import org.apache.abdera2.common.xml.XmlRestrictedCharReader;
+
+public class HtmlHelper {
+
+    private HtmlHelper() {
+    }
+
+    public static Div parse(String value) {
+        return parse(Abdera.getInstance(), value);
+    }
+
+    public static Div parse(InputStream in) {
+        return parse(Abdera.getInstance(), in);
+    }
+
+    public static Div parse(InputStream in, String charset) {
+        return parse(Abdera.getInstance(), in, charset);
+    }
+
+    public static Div parse(Reader in) {
+        return parse(Abdera.getInstance(), in);
+    }
+
+    public static Div parse(Abdera abdera, String value) {
+        return parse(abdera, new StringReader(value));
+    }
+
+    public static Div parse(Abdera abdera, InputStream in) {
+        return parse(abdera, in, "UTF-8");
+    }
+
+    public static Div parse(Abdera abdera, InputStream in, String charset) {
+        try {
+            return parse(abdera, new InputStreamReader(in, charset));
+        } catch (RuntimeException e) {
+            throw e;
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static Div parse(Abdera abdera, Reader in) {
+        Div div = abdera.getFactory().newDiv();
+        try {
+            String s = HtmlCleaner.parse(in, true);
+            div.setValue(s);
+            return div;
+        } catch (Throwable e) {
+            // this is a temporary hack. some html really
+            // can't be parsed successfully. in that case,
+            // we produce something that will likely render
+            // rather ugly. but there's not much else we
+            // can do
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static Document<Element> parseDocument(Reader in) {
+        return parseDocument(Abdera.getInstance(), in);
+    }
+
+    public static Document<Element> parseDocument(Abdera abdera, Reader in) {
+        return abdera.getParser().parse(new StringReader(HtmlCleaner.parse(in, false)));
+    }
+
+    /**
+     * This will search the element tree for elements named "link" with a rel attribute containing the value of rel and
+     * a type attribute containg the value of type.
+     */
+    public static Iterable<Element> discoverLinks(Element base, String type, String... rel) {
+        Set<Element> results = new LinkedHashSet<Element>();
+        walkElementForLinks(results, base, rel, type);
+        return results;
+    }
+
+    private static void walkElementForLinks(Set<Element> results, Element base, String[] rel, String type) {
+        if (checkElementForLink(base, rel, type))
+            results.add(base);
+        for (Element child : base.getElements())
+            walkElementForLinks(results, child, rel, type);
+    }
+
+    private static boolean checkElementForLink(Element base, String[] relvals, String type) {
+        if (base.getQName().getLocalPart().equalsIgnoreCase("link")) {
+            String relattr = base.getAttributeValue("rel");
+            String typeattr = base.getAttributeValue("type");
+            if (relattr != null) {
+                String[] rels = relattr.split("\\s+");
+                Arrays.sort(rels);
+                for (String rel : relvals) {
+                    if (Arrays.binarySearch(rels, rel) < 0)
+                        return false;
+                }
+            }
+            if (type != null && typeattr == null)
+                return false;
+            if (type == null && typeattr != null)
+                return true; // assume possible match
+            if (MimeTypeHelper.isMatch(type, typeattr))
+                return true;
+        }
+        return false;
+    }
+
+    public static Iterable<Element> discoverLinks(String uri, String type, String... rel) throws IOException {
+        return discoverLinks(Abdera.getInstance(), uri, type, rel);
+    }
+
+    public static Iterable<Element> discoverLinks(Abdera abdera, String uri, String type, String... rel) throws IOException {
+        Client client = new BasicClient();
+        try {
+          Session session = client.newSession();
+          ClientResponse resp = session.get(uri);
+          InputStream in = resp.getInputStream();
+          InputStreamReader r = new InputStreamReader(in);
+          XmlRestrictedCharReader x = new XmlRestrictedCharReader(r);
+          Document<Element> doc = HtmlHelper.parseDocument(x);
+          return discoverLinks(doc.getRoot(), type, rel);
+        } finally {
+          client.shutdown();
+        }
+    }
+}

Propchange: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/html/HtmlHelper.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/html/HtmlParser.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/html/HtmlParser.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/html/HtmlParser.java (added)
+++ abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/html/HtmlParser.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,74 @@
+/*
+ * 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.abdera2.ext.html;
+
+import java.io.Reader;
+
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.abdera2.Abdera;
+import org.apache.abdera2.common.anno.Name;
+import org.apache.abdera2.model.Div;
+import org.apache.abdera2.model.Document;
+import org.apache.abdera2.model.Element;
+import org.apache.abdera2.parser.AbstractParser;
+import org.apache.abdera2.parser.ParseException;
+import org.apache.abdera2.parser.ParserOptions;
+
+@Name("html")
+public class HtmlParser extends AbstractParser {
+
+    public HtmlParser() {
+        this(null);
+    }
+
+    public HtmlParser(Abdera abdera) {
+        super(abdera);
+    }
+
+    @Override
+    protected ParserOptions initDefaultParserOptions() {
+        return new HtmlParserOptions();
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T extends Element> Document<T> parse(Reader in, String base, ParserOptions options) throws ParseException {
+        boolean fragment = options instanceof HtmlParserOptions ? ((HtmlParserOptions)options).isHtmlFragment() : false;
+        Document<T> doc = null;
+        if (fragment) {
+            Div div = HtmlHelper.parse(abdera, in);
+            doc = this.getFactory().newDocument();
+            doc.setRoot((T)div);
+        } else {
+            doc = (Document<T>)HtmlHelper.parseDocument(abdera, in);
+        }
+        if (base != null)
+            doc.setBaseUri(base);
+        return doc;
+    }
+
+    public <T extends Element> Document<T> parse(XMLStreamReader reader) throws ParseException {
+        return null;
+    }
+
+    public <T extends Element> Document<T> parse(XMLStreamReader reader, String base, ParserOptions options)
+        throws ParseException {
+        return null;
+    }
+
+}

Propchange: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/html/HtmlParser.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/html/HtmlParserOptions.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/html/HtmlParserOptions.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/html/HtmlParserOptions.java (added)
+++ abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/html/HtmlParserOptions.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,49 @@
+/*
+ * 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.abdera2.ext.html;
+
+import org.apache.abdera2.common.Localizer;
+import org.apache.abdera2.factory.Factory;
+import org.apache.abdera2.parser.axiom.FOMException;
+import org.apache.abdera2.parser.axiom.FOMFactory;
+import org.apache.abdera2.parser.AbstractParserOptions;
+
+public class HtmlParserOptions extends AbstractParserOptions {
+
+    private boolean fragment = false;
+
+    @Override
+    protected void checkFactory(Factory factory) {
+        if (!(factory instanceof FOMFactory))
+            throw new FOMException(Localizer.sprintf("WRONG.PARSER.INSTANCE", FOMFactory.class.getName()));
+    }
+
+    @Override
+    protected void initFactory() {
+        if (factory == null)
+            factory = new FOMFactory();
+    }
+
+    public boolean isHtmlFragment() {
+        return fragment;
+    }
+
+    public void setHtmlFragment(boolean fragment) {
+        this.fragment = fragment;
+    }
+}

Propchange: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/html/HtmlParserOptions.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONFilter.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONFilter.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONFilter.java (added)
+++ abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONFilter.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,105 @@
+/*
+ * 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.abdera2.ext.json;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.abdera2.Abdera;
+import org.apache.abdera2.common.protocol.RequestContext;
+import org.apache.abdera2.common.protocol.ResponseContext;
+import org.apache.abdera2.common.protocol.Filter;
+import org.apache.abdera2.common.protocol.FilterChain;
+import org.apache.abdera2.common.protocol.ProviderHelper;
+import org.apache.abdera2.model.Document;
+import org.apache.abdera2.model.Element;
+import org.apache.abdera2.protocol.server.AtompubResponseContext;
+import org.apache.abdera2.protocol.server.context.ResponseContextWrapper;
+import org.apache.abdera2.writer.Writer;
+
+/**
+ * Filter implementation that will convert an Atom document returned by the server into a JSON document if the request
+ * specifies a higher preference value for JSON or explicitly requests JSON by including a format=json querystring
+ * parameter
+ */
+public class JSONFilter implements Filter {
+
+    @SuppressWarnings("unchecked")
+    public <S extends ResponseContext>S filter(RequestContext request, FilterChain chain) {
+        AtompubResponseContext resp = chain.next(request);
+        String format = request.getParameter("format");
+        return (S)((resp.getContentType() != null && jsonPreferred(request, resp.getContentType().toString())) || (format != null && format
+            .equalsIgnoreCase("json")) ? new JsonResponseContext(resp, Abdera.getInstance()) : resp);
+    }
+
+    private boolean jsonPreferred(RequestContext request, String type) {
+        return ProviderHelper.isPreferred(request, "application/json", type);
+    }
+
+    private class JsonResponseContext extends ResponseContextWrapper {
+
+        private final Abdera abdera;
+
+        public JsonResponseContext(AtompubResponseContext response, Abdera abdera) {
+            super(response);
+            setContentType("application/json");
+            this.abdera = abdera;
+        }
+
+        public void writeTo(OutputStream out, Writer writer) throws IOException {
+            try {
+                toJson(out, writer);
+            } catch (Exception se) {
+                if (se instanceof RuntimeException)
+                    throw (RuntimeException)se;
+                throw new RuntimeException(se);
+            }
+        }
+
+        public void writeTo(OutputStream out) throws IOException {
+            try {
+                toJson(out, null);
+            } catch (Exception se) {
+                if (se instanceof RuntimeException)
+                    throw (RuntimeException)se;
+                throw new RuntimeException(se);
+            }
+        }
+
+        private void toJson(OutputStream aout, Writer writer) throws Exception {
+            Document<Element> doc = null;
+            try {
+                ByteArrayOutputStream out = new ByteArrayOutputStream();
+                if (writer == null)
+                    super.writeTo(out);
+                else
+                    super.writeTo(out, writer);
+                ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
+                doc = abdera.getParser().parse(in);
+            } catch (Exception e) {
+            }
+            if (doc != null) {
+                doc.writeTo("json", aout);
+            } else {
+                throw new RuntimeException("There was an error serializing the entry to JSON");
+            }
+        }
+    }
+}

Propchange: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONFilter.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONServlet.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONServlet.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONServlet.java (added)
+++ abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONServlet.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,98 @@
+/*
+ * 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.abdera2.ext.json;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URLDecoder;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.abdera2.Abdera;
+import org.apache.abdera2.model.Document;
+import org.apache.abdera2.protocol.client.AbderaClient;
+import org.apache.abdera2.protocol.client.RequestHelper;
+import org.apache.abdera2.protocol.client.RequestOptions;
+
+/**
+ * Servlet that will do an HTTP GET to retrieve an Atom document then convert that into a JSON doc. The URL pattern is
+ * simple: http://.../servlet/path/{url}
+ */
+public class JSONServlet extends HttpServlet {
+
+    private static final long serialVersionUID = 1414392196430276024L;
+
+    private Abdera getAbdera() {
+        ServletContext sc = getServletContext();
+        Abdera abdera = null;
+        synchronized (sc) {
+            abdera = (Abdera)sc.getAttribute(Abdera.class.getName());
+            if (abdera == null) {
+                abdera = Abdera.getInstance();
+                sc.setAttribute(Abdera.class.getName(), abdera);
+            }
+        }
+        return abdera;
+    }
+
+    @Override
+    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+        String url = request.getPathInfo();
+        if (url != null && url.length() > 1)
+            url = URLDecoder.decode(url, "UTF-8");
+        else {
+            response.sendError(400);
+            return;
+        }
+        url = url.substring(1);
+
+        Abdera abdera = getAbdera();
+        AbderaClient client = new AbderaClient(abdera);
+        RequestOptions options = RequestHelper.createDefaultRequestOptions();
+        if (request.getHeader("If-Match") != null)
+            options.setIfMatch(request.getHeader("If-Match"));
+        if (request.getHeader("If-None-Match") != null)
+            options.setIfNoneMatch(request.getHeader("If-None-Match"));
+        if (request.getHeader("If-Modified-Since") != null)
+            options.setIfNoneMatch(request.getHeader("If-Modified-Since"));
+        if (request.getHeader("If-Unmodified-Since") != null)
+            options.setIfNoneMatch(request.getHeader("If-Unmodified-Since"));
+        try {
+            Document<?> doc = client.get(url);
+            response.setContentType("application/json");
+            response.setCharacterEncoding("UTF-8");
+            if (doc.getEntityTag() != null)
+                response.setHeader("ETag", doc.getEntityTag().toString());
+            if (doc.getLanguage() != null)
+                response.setHeader("Content-Language", doc.getLanguage());
+            if (doc.getLastModified() != null)
+                response.setDateHeader("Last-Modified", doc.getLastModified().getTime());
+            OutputStream out = response.getOutputStream();
+            doc.writeTo("json", out);
+        } catch (Exception e) {
+            response.sendError(500);
+            return;
+        }
+        client.shutdown();
+    }
+
+}

Propchange: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONServlet.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONStream.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONStream.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONStream.java (added)
+++ abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONStream.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,218 @@
+/*
+ * 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.abdera2.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.abdera2.common.iri.IRI;
+import org.apache.abdera2.common.date.DateTime;
+import org.apache.abdera2.common.http.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 {
+        if (value != null) {
+            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, DateTime.format(value));
+        }
+    }
+
+    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();
+    }
+}

Propchange: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONStream.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONUtil.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONUtil.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONUtil.java (added)
+++ abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONUtil.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,586 @@
+/*
+ * 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.abdera2.ext.json;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+
+import org.apache.abdera2.Abdera;
+import org.apache.abdera2.ext.bidi.BidiHelper;
+import org.apache.abdera2.ext.bidi.BidiHelper.Direction;
+import org.apache.abdera2.ext.history.FeedPagingHelper;
+import org.apache.abdera2.ext.html.HtmlHelper;
+import org.apache.abdera2.ext.thread.InReplyTo;
+import org.apache.abdera2.ext.thread.ThreadHelper;
+import org.apache.abdera2.common.iri.IRI;
+import org.apache.abdera2.model.Base;
+import org.apache.abdera2.model.Categories;
+import org.apache.abdera2.model.Category;
+import org.apache.abdera2.model.Collection;
+import org.apache.abdera2.model.Content;
+import org.apache.abdera2.model.Control;
+import org.apache.abdera2.model.Div;
+import org.apache.abdera2.model.Document;
+import org.apache.abdera2.model.Element;
+import org.apache.abdera2.model.Entry;
+import org.apache.abdera2.model.ExtensibleElement;
+import org.apache.abdera2.model.Feed;
+import org.apache.abdera2.model.Generator;
+import org.apache.abdera2.model.Link;
+import org.apache.abdera2.model.Person;
+import org.apache.abdera2.model.Service;
+import org.apache.abdera2.model.Source;
+import org.apache.abdera2.model.Text;
+import org.apache.abdera2.model.TextValue;
+import org.apache.abdera2.model.Workspace;
+import org.apache.abdera2.xpath.XPath;
+
+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<Categories> 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<QName> 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<QName> 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 is_empty(Iterable<?> list) {
+      for (@SuppressWarnings("unused") Object obj : list)
+        return false;
+      return true;
+    }
+    
+    private static boolean writeList(String name, Iterable<?> list, JSONStream jstream) throws IOException {
+        if (is_empty(list))
+            return false;
+        jstream.writeField(name);
+        jstream.startArray();
+        boolean start = true;
+        for (Object obj : list) {
+            Element el = (Element)obj;
+            if (!(el instanceof InReplyTo) && !(el instanceof Control)) {
+                if (!start) jstream.writeSeparator();
+                else start = false;
+                toJson(el, jstream);
+            }
+        }
+        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<?> 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);
+    }
+
+}

Propchange: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONUtil.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONWriter.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONWriter.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONWriter.java (added)
+++ abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONWriter.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,74 @@
+/*
+ * 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.abdera2.ext.json;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+
+import org.apache.abdera2.Abdera;
+import org.apache.abdera2.common.anno.Name;
+import org.apache.abdera2.model.Base;
+import org.apache.abdera2.writer.AbstractWriter;
+import org.apache.abdera2.writer.AbstractWriterOptions;
+import org.apache.abdera2.writer.WriterOptions;
+
+@Name("json")
+public class JSONWriter extends AbstractWriter {
+
+    public JSONWriter(Abdera abdera) {
+        super("application/json", "application/javascript", "application/ecmascript", "text/javascript", "text/ecmascript");
+    }
+
+    @Override
+    protected WriterOptions initDefaultWriterOptions() {
+        return new AbstractWriterOptions() {
+        };
+    }
+
+    public Object write(Base base, WriterOptions options) throws IOException {
+        try {
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            writeTo(base, out, options);
+            return new String(out.toByteArray(), options.getCharset());
+        } catch (IOException i) {
+            throw i;
+        } catch (Exception e) {
+            throw new IOException(e.getMessage());
+        }
+    }
+
+    public void writeTo(Base base, OutputStream out, WriterOptions options) throws IOException {
+        writeTo(base, new OutputStreamWriter(out, options.getCharset()), options);
+    }
+
+    public void writeTo(Base base, java.io.Writer out, WriterOptions options) throws IOException {
+        try {
+            JSONUtil.toJson(base, out);
+            out.flush();
+            if (options.getAutoClose())
+                out.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new IOException(e.getMessage());
+        }
+    }
+
+}

Propchange: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONWriter.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/license/LicenseHelper.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/license/LicenseHelper.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/license/LicenseHelper.java (added)
+++ abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/license/LicenseHelper.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,135 @@
+/*
+ * 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.abdera2.ext.license;
+
+import java.util.Collections;
+
+import org.apache.abdera2.common.iri.IRI;
+import org.apache.abdera2.model.Base;
+import org.apache.abdera2.model.Entry;
+import org.apache.abdera2.model.Link;
+import org.apache.abdera2.model.Source;
+
+/**
+ * Implementation of the Atom License Extension, RFC 4946
+ */
+public final class LicenseHelper {
+
+    public static final String UNSPECIFIED_LICENSE = 
+      "http://purl.org/atompub/license#unspecified";
+
+    LicenseHelper() {
+    }
+
+    @SuppressWarnings("unchecked")
+    public static Iterable<Link> getLicense(Base base, boolean inherited) {
+        Iterable<Link> links = null;
+        if (base instanceof Source) {
+            links = ((Source)base).getLinks(Link.REL_LICENSE);
+        } else if (base instanceof Entry) {
+            Entry entry = (Entry)base;
+            Source source = entry.getSource();
+            Base parent = entry.getParentElement();
+            links = entry.getLinks(Link.REL_LICENSE);
+            if (inherited && !contains(links) && source != null) {
+                links = getLicense(source, false);
+            }
+            
+            if (inherited && !contains(links) && parent != null) {
+                links = getLicense(parent, false);
+            }
+        }
+        return links == null ? Collections.EMPTY_SET : links;
+    }
+
+    @SuppressWarnings("unused")
+    private static boolean contains(Iterable<Link> list) {
+      if (list == null) return false;
+      for (Link link : list)
+        return true;
+      return false;
+    }
+    
+    public static Iterable<Link> getLicense(Base base) {
+        return getLicense(base, true);
+    }
+
+    public static boolean hasUnspecifiedLicense(Base base, boolean inherited) {
+        return hasLicense(base, UNSPECIFIED_LICENSE, inherited);
+    }
+
+    public static boolean hasUnspecifiedLicense(Base base) {
+        return hasUnspecifiedLicense(base, true);
+    }
+
+    public static boolean hasLicense(Base base, String iri, boolean inherited) {
+        Iterable<Link> links = getLicense(base, inherited);
+        IRI check = new IRI(iri);
+        if (links != null) {
+            for (Link link : links)
+                if (link.getResolvedHref().equals(check))
+                    return true;
+        }
+        return false;
+    }
+
+    public static boolean hasLicense(Base base, String iri) {
+        return hasLicense(base, iri, true);
+    }
+
+    public static boolean hasLicense(Base base, boolean inherited) {
+        Iterable<Link> links = getLicense(base, inherited);
+        for (@SuppressWarnings("unused") Link link : links)
+          return true; // if there's one... we're good
+        return false;
+    }
+
+    public static boolean hasLicense(Base base) {
+        return hasLicense(base, true);
+    }
+
+    public static Link addUnspecifiedLicense(Base base) {
+        if (hasUnspecifiedLicense(base, false))
+            throw new IllegalStateException("Unspecified license already added");
+        if (hasLicense(base, false))
+            throw new IllegalStateException("Other licenses are already added.");
+        return addLicense(base, UNSPECIFIED_LICENSE);
+    }
+
+    public static Link addLicense(Base base, String iri) {
+        return addLicense(base, iri, null, null, null);
+    }
+
+    public static Link addLicense(Base base, String iri, String title) {
+        return addLicense(base, iri, null, title, null);
+    }
+
+    public static Link addLicense(Base base, String iri, String type, String title, String hreflang) {
+        if (hasLicense(base, iri, false))
+            throw new IllegalStateException("License '" + iri + "' has already been added");
+        if (hasUnspecifiedLicense(base, false))
+            throw new IllegalStateException("Unspecified license already added");
+        if (base instanceof Source) {
+            return ((Source)base).addLink((new IRI(iri)).toString(), Link.REL_LICENSE, type, title, hreflang, -1);
+        } else if (base instanceof Entry) {
+            return ((Entry)base).addLink((new IRI(iri)).toString(), Link.REL_LICENSE, type, title, hreflang, -1);
+        }
+        return null;
+    }
+
+}

Propchange: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/license/LicenseHelper.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/license/LicensedEntrySelector.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/license/LicensedEntrySelector.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/license/LicensedEntrySelector.java (added)
+++ abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/license/LicensedEntrySelector.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,34 @@
+package org.apache.abdera2.ext.license;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.apache.abdera2.common.selector.Selector;
+import org.apache.abdera2.model.Entry;
+
+/**
+ * Used to only select entries that have the specified licenses or, if no
+ * licenses are specified, select entries that specify any license
+ */
+public class LicensedEntrySelector implements Selector {
+
+  private Set<String> set = new LinkedHashSet<String>();
+  
+  public LicensedEntrySelector(String... licenses) {
+    for (String license : licenses)
+      this.set.add(license);
+  }
+  
+  public boolean select(Object item) {
+    if (!(item instanceof Entry)) return false;
+    Entry entry = (Entry)item;
+    if (set.size() > 0) {
+      for (String license : set) 
+        if (LicenseHelper.hasLicense(entry, license, true))
+          return true;
+      return false;
+    } else 
+      return LicenseHelper.hasLicense(entry, true);
+  }
+
+}

Propchange: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/license/LicensedEntrySelector.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/license/UnspecifiedLicenseEntrySelector.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/license/UnspecifiedLicenseEntrySelector.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/license/UnspecifiedLicenseEntrySelector.java (added)
+++ abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/license/UnspecifiedLicenseEntrySelector.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,18 @@
+package org.apache.abdera2.ext.license;
+
+import org.apache.abdera2.common.selector.Selector;
+import org.apache.abdera2.model.Entry;
+
+/**
+ * Used to only select entries that do not specify a license
+ */
+public class UnspecifiedLicenseEntrySelector implements Selector {
+
+  public boolean select(Object item) {
+    if (!(item instanceof Entry))
+      return false;
+    Entry entry = (Entry)item;
+    return LicenseHelper.hasUnspecifiedLicense(entry, true);
+  }
+
+}

Propchange: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/license/UnspecifiedLicenseEntrySelector.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/media/MediaAdult.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/media/MediaAdult.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/media/MediaAdult.java (added)
+++ abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/media/MediaAdult.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,42 @@
+/*
+ * 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.abdera2.ext.media;
+
+import org.apache.abdera2.common.anno.QName;
+import org.apache.abdera2.factory.Factory;
+import org.apache.abdera2.model.Element;
+import org.apache.abdera2.model.ElementWrapper;
+import static org.apache.abdera2.ext.media.MediaConstants.*;
+
+/**
+ * @deprecated Use MediaRating instead
+ */
+@QName(value=LN_ADULT, 
+       ns=MEDIA_NS,
+       pfx=MEDIA_PREFIX)
+public class MediaAdult extends ElementWrapper {
+
+    public MediaAdult(Element internal) {
+        super(internal);
+    }
+
+    public MediaAdult(Factory factory) {
+        super(factory, ADULT);
+    }
+
+}

Propchange: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/media/MediaAdult.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Mime
View raw message