abdera-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jmsn...@apache.org
Subject svn commit: r1173209 [30/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/examples/src/main/java/org/apache/abdera2/examples/xsltxpath/XPathFunctionsExample.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/xsltxpath/XPathFunctionsExample.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/xsltxpath/XPathFunctionsExample.java (added)
+++ abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/xsltxpath/XPathFunctionsExample.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,99 @@
+/*
+ * 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.examples.xsltxpath;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+
+import org.apache.abdera2.Abdera;
+import org.apache.abdera2.model.Entry;
+import org.apache.abdera2.model.Feed;
+import org.apache.abdera2.model.Link;
+import org.apache.abdera2.model.Source;
+import org.apache.abdera2.parser.axiom.FOMXPath;
+import org.apache.abdera2.xpath.XPath;
+import org.apache.axiom.om.OMNode;
+import org.jaxen.Context;
+import org.jaxen.Function;
+import org.jaxen.FunctionCallException;
+
+public class XPathFunctionsExample {
+
+    public static void main(String... args) throws Exception {
+
+        Abdera abdera = Abdera.getInstance();
+        Feed feed = abdera.newFeed();
+        feed.setBaseUri("http://example.org/");
+        // add additional feed metadata
+        Entry entry = feed.addEntry();
+        // add additional feed metadata
+        entry.addLink("alternate.xml"); // relative URI
+
+        XPath xpath = abdera.getXPath();
+        System.out.println(xpath.valueOf("abdera:resolve(/a:feed/a:entry/a:link/@href)", feed));
+
+        // You can add your own xpath functions.
+        FOMXPath fxpath = (FOMXPath)xpath;
+        Map<QName, Function> functions = fxpath.getDefaultFunctions();
+        functions.put(AlternateLinkFunction.QNAME, new AlternateLinkFunction());
+        fxpath.setDefaultFunctions(functions);
+        List<?> links = fxpath.selectNodes("abdera:altlinks(/a:feed/a:entry)", feed);
+        System.out.println(links);
+    }
+
+    public static class AlternateLinkFunction implements Function {
+
+        public static final QName QNAME = new QName("http://abdera.apache.org", "altlinks");
+
+        @SuppressWarnings("rawtypes")
+        public Object call(Context context, List args) throws FunctionCallException {
+            List<Link> results = new ArrayList<Link>();
+            if (args.isEmpty())
+                return null;
+            for (Object obj : args) {
+                if (obj instanceof List) {
+                    for (Object o : (List)obj) {
+                        try {
+                            if (o instanceof OMNode) {
+                                OMNode node = (OMNode)o;
+                                List<Link> links = null;
+                                if (node instanceof Source) {
+                                    Source source = (Source)node;
+                                    links = source.getLinks("alternate");
+                                } else if (node instanceof Entry) {
+                                    Entry entry = (Entry)node;
+                                    links = entry.getLinks("alternate");
+                                }
+                                if (links != null)
+                                    results.addAll(links);
+                            }
+                        } catch (Exception e) {
+                        }
+                    }
+                } else {
+                    // nothing to do
+                }
+            }
+            return results;
+        }
+
+    }
+}

Propchange: abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/xsltxpath/XPathFunctionsExample.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/xsltxpath/XsltExample.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/xsltxpath/XsltExample.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/xsltxpath/XsltExample.java (added)
+++ abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/xsltxpath/XsltExample.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,85 @@
+/*
+ * 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.examples.xsltxpath;
+
+import java.io.ByteArrayOutputStream;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.abdera2.Abdera;
+import org.apache.abdera2.model.Content;
+import org.apache.abdera2.model.Document;
+import org.apache.abdera2.model.Element;
+import org.apache.abdera2.model.Entry;
+import org.apache.abdera2.model.Feed;
+import org.apache.abdera2.parser.Parser;
+import org.apache.abdera2.extra.AbderaSource;
+
+public class XsltExample {
+
+    public static void main(String[] args) {
+
+        Parser parser = Abdera.getInstance().getParser();
+
+        try {
+
+            // Apply an XSLT transform to the entire Feed
+            TransformerFactory factory = TransformerFactory.newInstance();
+
+            // Abdera is capable of parsing any well-formed XML document, even XSLT
+            Document<Element> xslt = parser.parse(XsltExample.class.getResourceAsStream("/test.xslt"));
+            AbderaSource xsltSource = new AbderaSource(xslt);
+            Transformer transformer = factory.newTransformer(xsltSource);
+
+            // Now let's get the feed we're going to transform
+            Document<Feed> feed = parser.parse(XsltExample.class.getResourceAsStream("/simple.xml"));
+            AbderaSource feedSource = new AbderaSource(feed);
+
+            // Prepare the output
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            Result result = new StreamResult(out);
+            transformer.transform(feedSource, result);
+            System.out.println(out); // "This is a test urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6"
+
+            // Apply an XSLT transform to XML in the content element
+            xslt = parser.parse(XsltExample.class.getResourceAsStream("/content.xslt"));
+            xsltSource = new AbderaSource(xslt);
+            transformer = factory.newTransformer(xsltSource);
+
+            feed = parser.parse(XsltExample.class.getResourceAsStream("/xmlcontent.xml"));
+            Entry entry = feed.getRoot().getEntries().get(0);
+            Content content = entry.getContentElement();
+            AbderaSource contentSource = new AbderaSource(content.getValueElement());
+
+            // Note that the AbderaSource is set to the value element of atom:content!!
+
+            out = new ByteArrayOutputStream();
+            result = new StreamResult(out);
+            transformer.transform(contentSource, result);
+            System.out.println(out); // "This is a test test"
+
+        } catch (Exception exception) {
+            // TrAX is likely not configured, skip the test
+        }
+
+    }
+
+}

Propchange: abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/xsltxpath/XsltExample.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/examples/src/main/resources/META-INF/services/org.apache.abdera.factory.ExtensionFactory
URL: http://svn.apache.org/viewvc/abdera/abdera2/examples/src/main/resources/META-INF/services/org.apache.abdera.factory.ExtensionFactory?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/examples/src/main/resources/META-INF/services/org.apache.abdera.factory.ExtensionFactory (added)
+++ abdera/abdera2/examples/src/main/resources/META-INF/services/org.apache.abdera.factory.ExtensionFactory Tue Sep 20 15:56:46 2011
@@ -0,0 +1 @@
+org.apache.abdera.examples.extension.FooExtensionFactory
\ No newline at end of file

Added: abdera/abdera2/examples/src/main/resources/atom-logo75px.gif
URL: http://svn.apache.org/viewvc/abdera/abdera2/examples/src/main/resources/atom-logo75px.gif?rev=1173209&view=auto
==============================================================================
Binary file - no diff available.

Propchange: abdera/abdera2/examples/src/main/resources/atom-logo75px.gif
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: abdera/abdera2/examples/src/main/resources/content.xslt
URL: http://svn.apache.org/viewvc/abdera/abdera2/examples/src/main/resources/content.xslt?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/examples/src/main/resources/content.xslt (added)
+++ abdera/abdera2/examples/src/main/resources/content.xslt Tue Sep 20 15:56:46 2011
@@ -0,0 +1,7 @@
+<xsl:stylesheet 
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
+  xmlns:a="http://example.org"
+  version="1.0" >
+  <xsl:output method="text" />
+  <xsl:template match = "/" >This is a test <xsl:value-of select="a:a/a:b/a:c" /></xsl:template>
+</xsl:stylesheet>
\ No newline at end of file

Propchange: abdera/abdera2/examples/src/main/resources/content.xslt
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/examples/src/main/resources/key.jks
URL: http://svn.apache.org/viewvc/abdera/abdera2/examples/src/main/resources/key.jks?rev=1173209&view=auto
==============================================================================
Binary file - no diff available.

Propchange: abdera/abdera2/examples/src/main/resources/key.jks
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: abdera/abdera2/examples/src/main/resources/log4j.properties
URL: http://svn.apache.org/viewvc/abdera/abdera2/examples/src/main/resources/log4j.properties?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/examples/src/main/resources/log4j.properties (added)
+++ abdera/abdera2/examples/src/main/resources/log4j.properties Tue Sep 20 15:56:46 2011
@@ -0,0 +1,5 @@
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.err
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%c{1}.%M: %m%n
+log4j.rootLogger=warn, stdout
\ No newline at end of file

Propchange: abdera/abdera2/examples/src/main/resources/log4j.properties
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/examples/src/main/resources/org/apache/abdera/examples/appserver/README
URL: http://svn.apache.org/viewvc/abdera/abdera2/examples/src/main/resources/org/apache/abdera/examples/appserver/README?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/examples/src/main/resources/org/apache/abdera/examples/appserver/README (added)
+++ abdera/abdera2/examples/src/main/resources/org/apache/abdera/examples/appserver/README Tue Sep 20 15:56:46 2011
@@ -0,0 +1,2 @@
+A simple, generally compliant, minimal APP Server implementation that 
+demonstrates the use of the server module for building APP servers.
\ No newline at end of file

Added: abdera/abdera2/examples/src/main/resources/org/apache/abdera/examples/appserver/web.xml
URL: http://svn.apache.org/viewvc/abdera/abdera2/examples/src/main/resources/org/apache/abdera/examples/appserver/web.xml?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/examples/src/main/resources/org/apache/abdera/examples/appserver/web.xml (added)
+++ abdera/abdera2/examples/src/main/resources/org/apache/abdera/examples/appserver/web.xml Tue Sep 20 15:56:46 2011
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app id="WebApp_ID" version="2.4" 
+  xmlns="http://java.sun.com/xml/ns/j2ee" 
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+  <display-name>Abdera Simple APP Server</display-name>
+  <servlet id="abdera">
+    <servlet-name>Abdera</servlet-name>  
+    <servlet-class>org.apache.abdera.protocol.server.servlet.AbderaServlet</servlet-class>
+    <init-param>
+      <param-name>org.apache.abdera.protocol.server.ServiceContext</param-name>
+      <param-value>org.apache.abdera.examples.appserver.SimpleServiceContext</param-value>
+    </init-param>
+  </servlet>
+  <servlet-mapping id="abdera-mapping">
+    <servlet-name>Abdera</servlet-name>
+    <url-pattern>/atom/*</url-pattern>
+  </servlet-mapping>
+  <welcome-file-list>
+    <welcome-file>index.jsp</welcome-file>
+  </welcome-file-list>
+</web-app>

Propchange: abdera/abdera2/examples/src/main/resources/org/apache/abdera/examples/appserver/web.xml
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/examples/src/main/resources/simple.xml
URL: http://svn.apache.org/viewvc/abdera/abdera2/examples/src/main/resources/simple.xml?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/examples/src/main/resources/simple.xml (added)
+++ abdera/abdera2/examples/src/main/resources/simple.xml Tue Sep 20 15:56:46 2011
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<feed xmlns="http://www.w3.org/2005/Atom" xml:base="http://example.org/">
+  
+  <title>Example Feed</title>
+  <link href=""/>
+  <updated>2003-12-13T18:30:02Z</updated>
+  <author>
+    <name>John Doe</name>
+  </author>
+  <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
+
+  <entry>
+    <title>Atom-Powered Robots Run Amok</title>
+    <link href="/2003/12/13/atom03"/>
+    <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
+    <updated>2003-12-13T18:30:02Z</updated>
+    <summary>Some text.</summary>
+  </entry>
+
+</feed>
\ No newline at end of file

Propchange: abdera/abdera2/examples/src/main/resources/simple.xml
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/examples/src/main/resources/test.xslt
URL: http://svn.apache.org/viewvc/abdera/abdera2/examples/src/main/resources/test.xslt?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/examples/src/main/resources/test.xslt (added)
+++ abdera/abdera2/examples/src/main/resources/test.xslt Tue Sep 20 15:56:46 2011
@@ -0,0 +1,7 @@
+<xsl:stylesheet 
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
+  xmlns:a="http://www.w3.org/2005/Atom"
+  version="1.0" >
+  <xsl:output method="text" />
+  <xsl:template match = "/" >This is a test <xsl:value-of select="a:feed/a:id" /></xsl:template>
+</xsl:stylesheet>
\ No newline at end of file

Propchange: abdera/abdera2/examples/src/main/resources/test.xslt
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/examples/src/main/resources/xmlcontent.xml
URL: http://svn.apache.org/viewvc/abdera/abdera2/examples/src/main/resources/xmlcontent.xml?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/examples/src/main/resources/xmlcontent.xml (added)
+++ abdera/abdera2/examples/src/main/resources/xmlcontent.xml Tue Sep 20 15:56:46 2011
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<feed xmlns="http://www.w3.org/2005/Atom">
+  
+  <title>Example Feed</title>
+  <link href="http://example.org/"/>
+  <updated>2003-12-13T18:30:02Z</updated>
+  <author>
+    <name>John Doe</name>
+  </author>
+  <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
+
+  <entry>
+    <title>Atom-Powered Robots Run Amok</title>
+    <link href="http://example.org/2003/12/13/atom03"/>
+    <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
+    <updated>2003-12-13T18:30:02Z</updated>
+    <content type="application/xml"><a xmlns="http://example.org"><b><c>test</c></b></a></content>
+  </entry>
+
+</feed>
\ No newline at end of file

Propchange: abdera/abdera2/examples/src/main/resources/xmlcontent.xml
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/examples/src/main/ruby/parse.rb
URL: http://svn.apache.org/viewvc/abdera/abdera2/examples/src/main/ruby/parse.rb?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/examples/src/main/ruby/parse.rb (added)
+++ abdera/abdera2/examples/src/main/ruby/parse.rb Tue Sep 20 15:56:46 2011
@@ -0,0 +1,45 @@
+#!/usr/bin/env jruby
+
+# 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.
+
+require 'java'
+
+Abdera = org.apache.abdera.Abdera
+URL    = java.net.URL
+
+if ARGV.length != 1 then
+  STDERR.print <<EOF
+Usage: parse.rb <url>
+EOF
+  exit 1
+end
+
+url = URL.new(ARGV[0])
+
+abdera = Abdera.new
+
+parser = abdera.parser
+
+doc = parser.parse(url.open_stream(), url.to_string())
+
+feed = doc.root
+
+print "#{feed.title}\n"
+
+for entry in feed.entries do
+  print "  #{entry.title} posted on #{entry.updated}\n"
+end

Propchange: abdera/abdera2/examples/src/main/ruby/parse.rb
------------------------------------------------------------------------------
    svn:executable = *

Added: abdera/abdera2/ext/pom.xml
URL: http://svn.apache.org/viewvc/abdera/abdera2/ext/pom.xml?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/ext/pom.xml (added)
+++ abdera/abdera2/ext/pom.xml Tue Sep 20 15:56:46 2011
@@ -0,0 +1,86 @@
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" 
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+  
+  <parent>
+    <groupId>org.apache.abdera2</groupId>
+    <artifactId>abdera2</artifactId>
+    <version>2.0-SNAPSHOT</version>  
+  </parent>  
+
+  <artifactId>abdera2-ext</artifactId>
+  <packaging>bundle</packaging>
+  <name>Abdera2 Extensions</name>
+  <version>2.0-SNAPSHOT</version>  
+  <description>Atom Publishing Protocol Client Implementation</description>
+
+  <properties>
+    <topDir>${basedir}/..</topDir>
+    <!-- 
+    <abdera.osgi.default.exports>
+	  	org.apache.abdera2.protocol.ext.*
+    </abdera.osgi.default.exports>
+    <abdera.osgi.default.imports>
+      org.apache.commons.codec*;version="[1.3,2)",
+      *
+    </abdera.osgi.default.imports>
+    -->
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.abdera2</groupId>
+      <artifactId>abdera2-core</artifactId>
+      <version>2.0-SNAPSHOT</version>  
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.abdera2</groupId>
+      <artifactId>abdera2-common</artifactId>
+      <version>2.0-SNAPSHOT</version>  
+      <scope>compile</scope>
+    </dependency>   
+    <dependency>
+      <groupId>org.apache.abdera2</groupId>
+      <artifactId>abdera2-server</artifactId>
+      <version>2.0-SNAPSHOT</version>  
+      <scope>compile</scope>
+    </dependency>  
+    <dependency>
+      <groupId>org.apache.abdera2</groupId>
+      <artifactId>abdera2-client</artifactId>
+      <version>2.0-SNAPSHOT</version>  
+      <scope>compile</scope>
+    </dependency> 
+    
+    <dependency>
+      <groupId>javax</groupId>
+      <artifactId>javaee-web-api</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>nu.validator.htmlparser</groupId>
+      <artifactId>htmlparser</artifactId>
+      <version>1.2.1</version>
+    </dependency>
+    
+   </dependencies>
+</project>

Propchange: abdera/abdera2/ext/pom.xml
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/bidi/BidiHelper.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/bidi/BidiHelper.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/bidi/BidiHelper.java (added)
+++ abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/bidi/BidiHelper.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,440 @@
+/*
+ * 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.bidi;
+
+import java.text.AttributedString;
+import java.util.Arrays;
+import java.util.Locale;
+
+import javax.xml.namespace.QName;
+
+import org.apache.abdera2.common.lang.Lang;
+import org.apache.abdera2.model.Base;
+import org.apache.abdera2.model.Document;
+import org.apache.abdera2.model.Element;
+
+/**
+ * <p>
+ * This is (hopefully) temporary. Ideally, this would be wrapped into the core model API so that the bidi stuff is
+ * handled seamlessly. There are still details being worked out on the Atom WG list and it's likely that at least one
+ * other impl (mozilla) will do something slightly different.
+ * </p>
+ * <p>
+ * Based on http://www.ietf.org/internet-drafts/draft-snell-atompub-bidi-04.txt
+ * </p>
+ * <p>
+ * Example:
+ * </p>
+ * 
+ * <pre>
+ *   &lt;feed xmlns="http://www.w3.org/2005/Atom" dir="rtl">
+ *     ...
+ *   &lt;/feed>
+ * </pre>
+ * <p>
+ * The getBidi___ elements use the in-scope direction to wrap the text with the appropriate Unicode control characters.
+ * e.g. if dir="rtl", the text is wrapped with the RLE and PDF controls. If the text already contains the control chars,
+ * the dir attribute is ignored.
+ * </p>
+ * 
+ * <pre>
+ * org.apache.abdera.Abdera abdera = new org.apache.abdera.Abdera();
+ * org.apache.abdera.model.Feed feed = abdera.getFactory().newFeed();
+ * feed.setAttributeValue(&quot;dir&quot;, &quot;rtl&quot;);
+ * feed.setTitle(&quot;Testing&quot;);
+ * feed.addCategory(&quot;foo&quot;);
+ * 
+ * System.out.println(BidiHelper.getBidiElementText(feed.getTitleElement()));
+ * System.out.println(BidiHelper.getBidiAttributeValue(feed.getCategories().get(0), &quot;term&quot;));
+ * </pre>
+ */
+public final class BidiHelper {
+
+    public static final QName DIR = new QName("dir");
+
+    BidiHelper() {
+    }
+
+    /**
+     * Set the value of dir attribute
+     */
+    public static <T extends Element> void setDirection(Direction direction, T element) {
+        if (direction != Direction.UNSPECIFIED)
+            element.setAttributeValue(DIR, direction.toString().toLowerCase());
+        else if (direction == Direction.UNSPECIFIED)
+            element.setAttributeValue(DIR, "");
+        else if (direction == null)
+            element.removeAttribute(DIR);
+    }
+
+    /**
+     * Get the in-scope direction for an element.
+     */
+    public static <T extends Element> Direction getDirection(T element) {
+        Direction direction = Direction.UNSPECIFIED;
+        String dir = element.getAttributeValue("dir");
+        if (dir != null && dir.length() > 0)
+            direction = Direction.valueOf(dir.toUpperCase());
+        else if (dir == null) {
+            // if the direction is unspecified on this element,
+            // let's see if we've inherited it
+            Base parent = element.getParentElement();
+            if (parent != null && parent instanceof Element)
+                direction = getDirection((Element)parent);
+        }
+        return direction;
+    }
+
+    /**
+     * Return the specified text with appropriate Unicode Control Characters given the specified Direction.
+     * 
+     * @param direction The Directionality of the text
+     * @param text The text to wrap within Unicode Control Characters
+     * @return The directionally-wrapped text
+     */
+    public static String getBidiText(Direction direction, String text) {
+        switch (direction) {
+            case LTR:
+                return wrapBidi(text, LRE);
+            case RTL:
+                return wrapBidi(text, RLE);
+            default:
+                return text;
+        }
+    }
+
+    /**
+     * Return the textual content of a child element using the in-scope directionality
+     * 
+     * @param element The parent element
+     * @param child The XML QName of the child element
+     * @return The directionally-wrapped text of the child element
+     */
+    public static <T extends Element> String getBidiChildText(T element, QName child) {
+        Element el = element.getFirstChild(child);
+        return (el != null) ? getBidiText(getDirection(el), el.getText()) : null;
+    }
+
+    /**
+     * Return the textual content of the specified element
+     * 
+     * @param element An element containing directionally-sensitive text
+     * @return The directionally-wrapped text of the element
+     */
+    public static <T extends Element> String getBidiElementText(T element) {
+        return getBidiText(getDirection(element), element.getText());
+    }
+
+    /**
+     * Return the text content of the specified attribute using the in-scope directionality
+     * 
+     * @param element The parent element
+     * @param name the name of the attribute
+     * @return The directionally-wrapped text of the attribute
+     */
+    public static <T extends Element> String getBidiAttributeValue(T element, String name) {
+        return getBidiText(getDirection(element), element.getAttributeValue(name));
+    }
+
+    /**
+     * Return the text content of the specified attribute using the in-scope directionality
+     * 
+     * @param element The parent element
+     * @param name the name of the attribute
+     * @return The directionally-wrapped text of the attribute
+     */
+    public static <T extends Element> String getBidiAttributeValue(T element, QName name) {
+        return getBidiText(getDirection(element), element.getAttributeValue(name));
+    }
+
+    /**
+     * Attempt to guess the base direction using the in-scope language. Implements the method used by Internet Explorer
+     * 7's feed view documented here:
+     * http://blogs.msdn.com/rssteam/archive/2007/05/17/reading-feeds-in-right-to-left-order.aspx. This algorithm
+     * differs slightly from the method documented in that the primary language tag is case insensitive. If the language
+     * tag is not specified, then the default Locale is used to determine the direction. If the dir attribute is
+     * specified, the direction will be determine using it's value instead of the language
+     */
+    public static <T extends Element> Direction guessDirectionFromLanguage(T element) {
+        return guessDirectionFromLanguage(element, false);
+    }
+
+    /**
+     * Attempt to guess the base direction using the in-scope language. Implements the method used by Internet Explorer
+     * 7's feed view documented here:
+     * http://blogs.msdn.com/rssteam/archive/2007/05/17/reading-feeds-in-right-to-left-order.aspx. This algorithm
+     * differs slightly from the method documented in that the primary language tag is case insensitive. If the language
+     * tag is not specified, then the default Locale is used to determine the direction. According to the Atom Bidi
+     * spec, if the dir attribute is set explicitly, we should not do language guessing. This restriction can be
+     * bypassed by setting ignoredir to true.
+     */
+    public static <T extends Element> Direction guessDirectionFromLanguage(T element, boolean ignoredir) {
+        if (!ignoredir && hasDirection(element))
+            return getDirection(element);
+        String language = element.getLanguage();
+        Lang lang = language != null ? new Lang(language) : new Lang(Locale.getDefault());
+        return guessDirectionFromLanguage(lang);
+    }
+
+    /**
+     * Attempt to guess the base direction using the charset encoding. This is a bit of a last resort approach
+     */
+    public static <T extends Element> Direction guessDirectionFromEncoding(T element) {
+        return guessDirectionFromEncoding(element, false);
+    }
+
+    /**
+     * Attempt to guess the base direction using the charset encoding. This is a bit of a last resort approach
+     */
+    public static <T extends Element> Direction guessDirectionFromEncoding(T element, boolean ignoredir) {
+        if (!ignoredir && hasDirection(element))
+            return getDirection(element);
+        Document<T> doc = element.getDocument();
+        if (doc == null)
+            return Direction.UNSPECIFIED;
+        return guessDirectionFromEncoding(doc.getCharset());
+    }
+
+    /**
+     * Attempt to guess the base direction of an element using an analysis of the directional properties of the
+     * characters used. This is a brute-force style approach that can achieve fairly reasonable results when the element
+     * text consists primarily of characters with the same bidi properties. This approach is implemented by the Snarfer
+     * feed reader as is documented at http://www.xn--8ws00zhy3a.com/blog/2006/12/right-to-left-rss If the dir attribute
+     * is specified, the direction will be determine using it's value instead of the characteristics of the text
+     */
+    public static <T extends Element> Direction guessDirectionFromTextProperties(T element) {
+        return guessDirectionFromTextProperties(element, false);
+    }
+
+    /**
+     * Attempt to guess the base direction of an element using an analysis of the directional properties of the
+     * characters used. This is a brute-force style approach that can achieve fairly reasonable results when the element
+     * text consists primarily of characters with the same bidi properties. This approach is implemented by the Snarfer
+     * feed reader as is documented at http://www.xn--8ws00zhy3a.com/blog/2006/12/right-to-left-rss According to the
+     * Atom Bidi spec, if the dir attribute is set explicitly, we should not do language guessing. This restriction can
+     * be bypassed by setting ignoredir to true.
+     */
+    public static <T extends Element> Direction guessDirectionFromTextProperties(T element, boolean ignoredir) {
+        if (!ignoredir && hasDirection(element))
+            return getDirection(element);
+        return guessDirectionFromTextProperties(element.getText());
+    }
+
+    /**
+     * Use Java's built in support for bidi text to determine the base directionality of the element's text. The
+     * response to this only indicates the *base* directionality, it does not indicate whether or not there are any RTL
+     * characters in the text. If the dir attribute is specified, the direction will be determine using it's value
+     * instead of the characteristics of the text
+     */
+    public static <T extends Element> Direction guessDirectionFromJavaBidi(T element) {
+        return guessDirectionFromJavaBidi(element, false);
+    }
+
+    /**
+     * Use Java's built in support for bidi text to determine the base directionality of the element's text. The
+     * response to this only indicates the *base* directionality, it does not indicate whether or not there are any RTL
+     * characters in the text. According to the Atom Bidi spec, if the dir attribute is set explicitly, we should not do
+     * language guessing. This restriction can be bypassed by setting ignoredir to true.
+     */
+    public static <T extends Element> Direction guessDirectionFromJavaBidi(T element, boolean ignoredir) {
+        if (!ignoredir && hasDirection(element))
+            return getDirection(element);
+        return guessDirectionFromJavaBidi(element.getText());
+    }
+
+    private static <T extends Element> boolean hasDirection(T element) {
+        String dir = element.getAttributeValue("dir");
+        if (dir != null && dir.length() > 0)
+            return true;
+        else if (dir == null) {
+            // if the direction is unspecified on this element,
+            // let's see if we've inherited it
+            Base parent = element.getParentElement();
+            if (parent != null && parent instanceof Element)
+                return hasDirection((Element)parent);
+        }
+        return false;
+    }
+    
+    public enum Direction {
+      UNSPECIFIED, LTR, RTL
+  };
+
+  private static final String[] RTL_LANGS = {"ar", "dv", "fa", "he", "ps", "syr", "ur", "yi"};
+
+  private static final String[] RTL_SCRIPTS =
+      {"arab", "avst", "hebr", "hung", "lydi", "mand", "mani", "mero", "mong", "nkoo", "orkh", "phlv", "phnx",
+       "samr", "syrc", "syre", "syrj", "syrn", "tfng", "thaa"};
+  // charset encodings that one may typically expect to be RTL
+  private static final String[] RTL_ENCODINGS =
+      {"iso-8859-6", "iso-8859-6-bidi", "iso-8859-6-i", "iso-ir-127", "ecma-114", "asmo-708", "arabic",
+       "csisolatinarabic", "windows-1256", "ibm-864", "macarabic", "macfarsi", "iso-8859-8-i", "iso-8859-8-bidi",
+       "windows-1255", "iso-8859-8", "ibm-862", "machebrew", "asmo-449", "iso-9036", "arabic7", "iso-ir-89",
+       "csiso89asmo449", "iso-unicode-ibm-1264", "csunicodeibm1264", "iso_8859-8:1988", "iso-ir-138", "hebrew",
+       "csisolatinhebrew", "iso-unicode-ibm-1265", "csunicodeibm1265", "cp862", "862", "cspc862latinhebrew"};
+
+  /**
+   * Algorithm that will determine text direction by looking at the characteristics of the language tag. If the tag
+   * uses a language or script that is known to be RTL, then Direction.RTL will be returned
+   */
+  public static Direction guessDirectionFromLanguage(Lang lang) {
+      if (lang.script() != null) {
+          String script = lang.script().name();
+          if (Arrays.binarySearch(RTL_SCRIPTS, script.toLowerCase()) > -1)
+              return Direction.RTL;
+      }
+      String primary = lang.language().name();
+      if (Arrays.binarySearch(RTL_LANGS, primary.toLowerCase()) > -1)
+          return Direction.RTL;
+      return Direction.UNSPECIFIED;
+  }
+
+  /**
+   * Algorithm that will determine text direction by looking at the character set encoding. If the charset is
+   * typically used for RTL languages, Direction.RTL will be returned
+   */
+  public static Direction guessDirectionFromEncoding(String charset) {
+      if (charset == null)
+          return Direction.UNSPECIFIED;
+      charset = charset.replace('_', '-');
+      Arrays.sort(RTL_ENCODINGS);
+      if (Arrays.binarySearch(RTL_ENCODINGS, charset.toLowerCase()) > -1)
+          return Direction.RTL;
+      return Direction.UNSPECIFIED;
+  }
+
+  /**
+   * Algorithm that analyzes properties of the text to determine text direction. If the majority of characters in the
+   * text are RTL characters, then Direction.RTL will be returned.
+   */
+  public static Direction guessDirectionFromTextProperties(String text) {
+      if (text != null && text.length() > 0) {
+          if (text.charAt(0) == 0x200F)
+              return Direction.RTL; // if using the unicode right-to-left mark
+          if (text.charAt(0) == 0x200E)
+              return Direction.LTR; // if using the unicode left-to-right mark
+          int c = 0;
+          for (int n = 0; n < text.length(); n++) {
+              char ch = text.charAt(n);
+              if (java.text.Bidi.requiresBidi(new char[] {ch}, 0, 1))
+                  c++;
+              else
+                  c--;
+          }
+          return c > 0 ? Direction.RTL : Direction.LTR;
+      }
+      return Direction.UNSPECIFIED;
+  }
+
+  /**
+   * Algorithm that defers to the Java Bidi implementation to determine text direction.
+   */
+  public static Direction guessDirectionFromJavaBidi(String text) {
+      if (text != null) {
+          AttributedString s = new AttributedString(text);
+          java.text.Bidi bidi = new java.text.Bidi(s.getIterator());
+          return bidi.baseIsLeftToRight() ? Direction.LTR : Direction.RTL;
+      }
+      return Direction.UNSPECIFIED;
+  }
+  
+  public static final char LRE = 0x202A;
+  public static final char RLE = 0x202B;
+  public static final char LRO = 0x202D;
+  public static final char RLO = 0x202E;
+  public static final char LRM = 0x200E;
+  public static final char RLM = 0x200F;
+  public static final char PDF = 0x202C;
+
+  /**
+   * Removes leading and trailing bidi controls from the string
+   */
+  public static String stripBidi(String s) {
+      if (s == null || s.length() <= 1)
+          return s;
+      if (isBidi(s.charAt(0)))
+          s = s.substring(1);
+      if (isBidi(s.charAt(s.length() - 1)))
+          s = s.substring(0, s.length() - 1);
+      return s;
+  }
+
+  /**
+   * Removes bidi controls from within a string
+   */
+  public static String stripBidiInternal(String s) {
+    StringBuilder buf = new StringBuilder();
+    char[] chars = s.toCharArray();
+    for (char c : chars) {
+      if (!isBidi(c))
+        buf.append(c);
+    }
+    return buf.toString();
+  }
+
+  private static String wrap(String s, char c1, char c2) {
+      StringBuilder buf = new StringBuilder(s);
+      if (buf.length() > 1) {
+          if (buf.charAt(0) != c1)
+              buf.insert(0, c1);
+          if (buf.charAt(buf.length() - 1) != c2)
+              buf.append(c2);
+      }
+      return buf.toString();
+  }
+
+  /**
+   * Wrap the string with the specified bidi control
+   */
+  public static String wrapBidi(String s, char c) {
+      switch (c) {
+          case RLE:
+              return wrap(s, RLE, PDF);
+          case RLO:
+              return wrap(s, RLO, PDF);
+          case LRE:
+              return wrap(s, LRE, PDF);
+          case LRO:
+              return wrap(s, LRO, PDF);
+          case RLM:
+              return wrap(s, RLM, RLM);
+          case LRM:
+              return wrap(s, LRM, LRM);
+          default:
+              return s;
+      }
+  }
+
+  /**
+   * True if the codepoint is a bidi control character
+   */
+  public static boolean isBidi(int codepoint) {
+      return codepoint == LRM || // Left-to-right mark
+      codepoint == RLM
+          || // Right-to-left mark
+          codepoint == LRE
+          || // Left-to-right embedding
+          codepoint == RLE
+          || // Right-to-left embedding
+          codepoint == LRO
+          || // Left-to-right override
+          codepoint == RLO
+          || // Right-to-left override
+          codepoint == PDF; // Pop directional formatting
+  }
+}

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

Added: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/features/Feature.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/features/Feature.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/features/Feature.java (added)
+++ abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/features/Feature.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,110 @@
+/*
+ * 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.features;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.activation.MimeType;
+import javax.activation.MimeTypeParseException;
+
+import org.apache.abdera2.factory.Factory;
+import org.apache.abdera2.common.anno.QName;
+import org.apache.abdera2.common.iri.IRI;
+import org.apache.abdera2.model.Element;
+import org.apache.abdera2.model.ExtensibleElementWrapper;
+import org.apache.abdera2.common.mediatype.MimeTypeHelper;
+import static org.apache.abdera2.ext.features.FeaturesHelper.*;
+
+@QName(value="feature", 
+    ns=FNS,
+    pfx=FPX)
+public class Feature extends ExtensibleElementWrapper {
+
+    public Feature(Element internal) {
+        super(internal);
+    }
+    
+    public Feature(Factory factory, javax.xml.namespace.QName qname) {
+        super(factory, qname);
+    }
+
+    public IRI getRef() {
+        String ref = getAttributeValue("ref");
+        return (ref != null) ? new IRI(ref) : null;
+    }
+
+    public IRI getHref() {
+        String href = getAttributeValue("href");
+        return (href != null) ? new IRI(href) : null;
+    }
+
+    public String getLabel() {
+        return getAttributeValue("label");
+    }
+
+    public void setRef(String ref) {
+        if (ref == null)
+            throw new IllegalArgumentException();
+        setAttributeValue("ref", (new IRI(ref)).toString());
+    }
+
+    public void setHref(String href) {
+        if (href != null)
+            setAttributeValue("href", (new IRI(href)).toString());
+        else
+            removeAttribute("href");
+    }
+
+    public void setLabel(String label) {
+        if (label != null)
+            setAttributeValue("label", label);
+        else
+            removeAttribute("label");
+    }
+
+    public void addType(String mediaRange) {
+        addType(new String[] {mediaRange});
+    }
+
+    public void addType(String... mediaRanges) {
+        mediaRanges = MimeTypeHelper.condense(mediaRanges);
+        for (String mediaRange : mediaRanges) {
+            try {
+                addSimpleExtension(FeaturesHelper.TYPE, new MimeType(mediaRange).toString());
+            } catch (MimeTypeParseException e) {
+            }
+        }
+    }
+
+    public Iterable<String> getTypes() {
+        Set<String> list = new HashSet<String>();
+        for (Element type : getExtensions(FeaturesHelper.TYPE)) {
+            String value = type.getText();
+            if (value != null) {
+                value = value.trim();
+                try {
+                    list.add(new MimeType(value).toString());
+                } catch (MimeTypeParseException e) {
+                }
+            }
+        }
+        return list;
+    }
+
+}

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

Added: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/features/FeatureSelector.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/features/FeatureSelector.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/features/FeatureSelector.java (added)
+++ abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/features/FeatureSelector.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,81 @@
+/*
+ * 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.features;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.apache.abdera2.common.selector.Selector;
+import org.apache.abdera2.ext.features.FeaturesHelper.Status;
+import org.apache.abdera2.model.Collection;
+
+public class FeatureSelector implements Selector {
+
+    private static final long serialVersionUID = -8943638085557912175L;
+    private final Set<String> features = new LinkedHashSet<String>();
+
+    FeatureSelector(Set<String> features) {
+      this.features.addAll(features);
+    }
+    
+    public FeatureSelector(String... features) {
+        for (String feature : features)
+            this.features.add(feature);
+    }
+
+    public boolean select(Object item) {
+      if (!(item instanceof Collection)) return false;
+      Collection collection = (Collection)item;
+        for (String feature : features) {
+            Status status = FeaturesHelper.getFeatureStatus(collection, feature);
+            if (status == Status.SPECIFIED)
+                return true;
+        }
+        return false;
+    }
+
+    public Iterable<String> getFeatures() {
+        return features;
+    }
+
+    @Override
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * result + ((features == null) ? 0 : features.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        final FeatureSelector other = (FeatureSelector)obj;
+        if (features == null) {
+            if (other.features != null)
+                return false;
+        } else if (!features.equals(other.features))
+            return false;
+        return true;
+    }
+
+}

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

Added: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/features/Features.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/features/Features.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/features/Features.java (added)
+++ abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/features/Features.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,97 @@
+/*
+ * 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.features;
+
+import java.util.List;
+
+import org.apache.abdera2.factory.Factory;
+import org.apache.abdera2.common.anno.QName;
+import org.apache.abdera2.common.iri.IRI;
+import org.apache.abdera2.model.Element;
+import org.apache.abdera2.model.ExtensibleElementWrapper;
+import static org.apache.abdera2.ext.features.FeaturesHelper.*;
+
+@QName(value="features", 
+    ns=FNS,
+    pfx=FPX)
+public class Features extends ExtensibleElementWrapper {
+
+    public Features(Element internal) {
+        super(internal);
+    }
+
+    public Features(Factory factory, javax.xml.namespace.QName qname) {
+        super(factory, qname);
+    }
+
+    public IRI getResolvedHref() {
+        IRI base = getResolvedBaseUri();
+        IRI href = getHref();
+        return base != null ? base.resolve(href) : href;
+    }
+
+    public IRI getHref() {
+        String href = getAttributeValue("href");
+        return href != null ? new IRI(href) : null;
+    }
+
+    public void setHref(String href) {
+        setAttributeValue("href", (new IRI(href)).toString());
+    }
+
+    public String getName() {
+        return getAttributeValue("name");
+    }
+
+    public void setName(String name) {
+        setAttributeValue("name", name);
+    }
+
+    public void addFeature(Feature feature) {
+        addExtension(feature);
+    }
+
+    public void addFeature(Feature... features) {
+        for (Feature feature : features)
+            addFeature(feature);
+    }
+
+    public Feature addFeature(String feature) {
+        Feature f = addExtension(FeaturesHelper.FEATURE);
+        f.setRef(feature);
+        return f;
+    }
+
+    public Feature addFeature(String feature, String href, String label) {
+        Feature f = addExtension(FeaturesHelper.FEATURE);
+        f.setRef(feature);
+        f.setHref(href);
+        f.setLabel(label);
+        return f;
+    }
+
+    public Iterable<Feature> addFeatures(String... features) {
+        for (String feature : features)
+            addFeature(feature);
+        return getFeatures();
+    }
+
+    public List<Feature> getFeatures() {
+        return getExtensions(FeaturesHelper.FEATURE);
+    }
+}

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

Added: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/features/FeaturesExtensionFactory.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/features/FeaturesExtensionFactory.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/features/FeaturesExtensionFactory.java (added)
+++ abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/features/FeaturesExtensionFactory.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,31 @@
+/*
+ * 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.features;
+
+import org.apache.abdera2.common.anno.Namespace;
+import org.apache.abdera2.factory.AbstractExtensionFactory;
+import org.apache.abdera2.factory.AbstractExtensionFactory.Impl;
+import org.apache.abdera2.factory.AbstractExtensionFactory.Impls;
+
+@Namespace({"http://purl.org/atompub/features/1.0"})
+@Impls({
+  @Impl(Feature.class),
+  @Impl(Features.class)
+})
+public final class FeaturesExtensionFactory 
+  extends AbstractExtensionFactory {}

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

Added: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/features/FeaturesHelper.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/features/FeaturesHelper.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/features/FeaturesHelper.java (added)
+++ abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/features/FeaturesHelper.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,327 @@
+/*
+ * 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.features;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.xml.namespace.QName;
+
+import org.apache.abdera2.Abdera;
+import org.apache.abdera2.common.selector.MultiSelector;
+import org.apache.abdera2.common.selector.Selector;
+import org.apache.abdera2.factory.Factory;
+import org.apache.abdera2.model.Collection;
+import org.apache.abdera2.model.Document;
+import org.apache.abdera2.model.Element;
+import org.apache.abdera2.model.Service;
+import org.apache.abdera2.model.Workspace;
+import org.apache.abdera2.protocol.client.AbderaClient;
+
+/**
+ * Implementation of the current APP Features Draft
+ * (http://www.ietf.org/internet-drafts/draft-snell-atompub-feature-08.txt)
+ */
+public final class FeaturesHelper {
+
+    public enum Status {
+        UNSPECIFIED, SPECIFIED
+    }
+
+    public static final String FPX = "f";
+    public static final String FNS = "http://purl.org/atompub/features/1.0";
+    public static final QName FEATURE = new QName(FNS, "feature", FPX);
+    public static final QName FEATURES = new QName(FNS, "features", FPX);
+    public static final QName TYPE = new QName(FNS, "type", FPX);
+
+    private static final String FEATURE_BASE = "http://www.w3.org/2007/app/";
+    private static final String ABDERA_FEATURE_BASE = "http://abdera.apache.org/features/";
+    private static final String BLOG_FEATURE_BASE = "http://abdera.apache.org/features/blog/";
+    public static final String FEATURE_SUPPORTS_DRAFTS = FEATURE_BASE + "supportsDraft";
+    public static final String FEATURE_IGNORES_DRAFTS = FEATURE_BASE + "ignoresDraft";
+
+    public static final String FEATURE_SUPPORTS_XHTML_CONTENT = ABDERA_FEATURE_BASE + "supportsXhtmlContent";
+    public static final String FEATURE_REQUIRES_XHTML_CONTENT = ABDERA_FEATURE_BASE + "requiresXhtmlContent";
+    public static final String FEATURE_SUPPORTS_HTML_CONTENT = ABDERA_FEATURE_BASE + "supportsHtmlContent";
+    public static final String FEATURE_REQUIRES_HTML_CONTENT = ABDERA_FEATURE_BASE + "requiresHtmlContent";
+    public static final String FEATURE_SUPPORTS_TEXT_CONTENT = ABDERA_FEATURE_BASE + "supportsTextContent";
+    public static final String FEATURE_REQUIRES_TEXT_CONTENT = ABDERA_FEATURE_BASE + "requiresTextContent";
+    public static final String FEATURE_SUPPORTS_XML_CONTENT = ABDERA_FEATURE_BASE + "supportsXmlContent";
+    public static final String FEATURE_REQUIRES_XML_CONTENT = ABDERA_FEATURE_BASE + "requiresXmlContent";
+    public static final String FEATURE_SUPPORTS_BINARY_CONTENT = ABDERA_FEATURE_BASE + "supportsBinaryContent";
+    public static final String FEATURE_REQUIRES_BINARY_CONTENT = ABDERA_FEATURE_BASE + "requiresBinaryContent";
+    public static final String FEATURE_SUPPORTS_REF_CONTENT = ABDERA_FEATURE_BASE + "supportsRefContent";
+    public static final String FEATURE_REQUIRES_REF_CONTENT = ABDERA_FEATURE_BASE + "requiresRefContent";
+    public static final String FEATURE_SUPPORTS_XHTML_TEXT = ABDERA_FEATURE_BASE + "supportsXhtmlText";
+    public static final String FEATURE_REQUIRES_XHTML_TEXT = ABDERA_FEATURE_BASE + "requiresXhtmlText";
+    public static final String FEATURE_SUPPORTS_HTML_TEXT = ABDERA_FEATURE_BASE + "supportsHtmlText";
+    public static final String FEATURE_REQUIRES_HTML_TEXT = ABDERA_FEATURE_BASE + "requiresHtmlText";
+    public static final String FEATURE_SUPPORTS_TEXT_TEXT = ABDERA_FEATURE_BASE + "supportsTextText";
+    public static final String FEATURE_REQUIRES_TEXT_TEXT = ABDERA_FEATURE_BASE + "requiresTextText";
+    public static final String FEATURE_PRESERVES_SUMMARY = ABDERA_FEATURE_BASE + "preservesSummary";
+    public static final String FEATURE_IGNORES_SUMMARY = ABDERA_FEATURE_BASE + "ignoresSummary";
+    public static final String FEATURE_PRESERVES_RIGHTS = ABDERA_FEATURE_BASE + "preservesRights";
+    public static final String FEATURE_IGNORES_RIGHTS = ABDERA_FEATURE_BASE + "ignoresRights";
+    public static final String FEATURE_PRESERVES_AUTHORS = ABDERA_FEATURE_BASE + "preservesAuthors";
+    public static final String FEATURE_IGNORES_AUTHORS = ABDERA_FEATURE_BASE + "ignoresAuthors";
+    public static final String FEATURE_PRESERVES_CONTRIBUTORS = ABDERA_FEATURE_BASE + "preservesContributors";
+    public static final String FEATURE_IGNORES_CONTRIBUTORS = ABDERA_FEATURE_BASE + "ignoresContributors";
+    public static final String FEATURE_USES_SLUG = ABDERA_FEATURE_BASE + "usesSlug";
+    public static final String FEATURE_IGNORES_SLUG = ABDERA_FEATURE_BASE + "ignoresSlug";
+    public static final String FEATURE_PRESERVES_CATEGORIES = ABDERA_FEATURE_BASE + "preservesCategories";
+    public static final String FEATURE_MULTIPLE_CATEGORIES = ABDERA_FEATURE_BASE + "multipleCategories";
+    public static final String FEATURE_IGNORES_CATEGORIES = ABDERA_FEATURE_BASE + "ignoresCategories";
+    public static final String FEATURE_PRESERVES_LINKS = ABDERA_FEATURE_BASE + "preservesLinks";
+    public static final String FEATURE_IGNORES_LINKS = ABDERA_FEATURE_BASE + "ignoresLinks";
+    public static final String FEATURE_PRESERVES_INFOSET = ABDERA_FEATURE_BASE + "preservesInfoset";
+    public static final String FEATURE_PRESERVES_ID = ABDERA_FEATURE_BASE + "preservesId";
+    public static final String FEATURE_PRESERVES_DATES = ABDERA_FEATURE_BASE + "preservesDates";
+    public static final String FEATURE_PRESERVES_EXTENSIONS = ABDERA_FEATURE_BASE + "preservesExtensions";
+    public static final String FEATURE_SCHEDULED_PUBLISHING = ABDERA_FEATURE_BASE + "scheduledPublishing";
+    public static final String FEATURE_REQUIRES_PERSON_EMAIL = ABDERA_FEATURE_BASE + "requiresPersonEmail";
+    public static final String FEATURE_HIDES_PERSON_EMAIL = ABDERA_FEATURE_BASE + "hidesPersonEmail";
+    public static final String FEATURE_REQUIRES_PERSON_URI = ABDERA_FEATURE_BASE + "requiresPersonUri";
+    public static final String FEATURE_HIDES_PERSON_URI = ABDERA_FEATURE_BASE + "hidesPersonUri";
+    public static final String FEATURE_PRESERVES_LANGUAGE = ABDERA_FEATURE_BASE + "preservesXmlLang";
+    public static final String FEATURE_IGNORES_LANGUAGE = ABDERA_FEATURE_BASE + "ignoresXmlLang";
+    public static final String FEATURE_SUPPORTS_CONDITIONALS = ABDERA_FEATURE_BASE + "supportsConditionalUpdates";
+    public static final String FEATURE_REQUIRES_CONDITIONALS = ABDERA_FEATURE_BASE + "requiresConditionalUpdates";
+    public static final String FEATURE_PRESERVES_THREADING = ABDERA_FEATURE_BASE + "preservesThreading";
+    public static final String FEATURE_REQUIRES_THREADING = ABDERA_FEATURE_BASE + "requiresThreading";
+    public static final String FEATURE_IGNORES_THREADING = ABDERA_FEATURE_BASE + "ignoresThreading";
+
+    /**
+     * Indicates that the collection will preserve XML digital signatures contained in member resources
+     */
+    public static final String FEATURE_PRESERVE_SIGNATURE = ABDERA_FEATURE_BASE + "preservesSignature";
+
+    /**
+     * Indicates that the collection will support XML digital signatures contained in member resources but may not
+     * preserve those signatures
+     */
+    public static final String FEATURE_SUPPORTS_SIGNATURE = ABDERA_FEATURE_BASE + "supportsSignature";
+
+    /**
+     * Indicates that the collection will ignore XML digital signatures contained in member resources
+     */
+    public static final String FEATURE_IGNORES_SIGNATURE = ABDERA_FEATURE_BASE + "ignoresSignature";
+
+    /**
+     * Indicates that the collection requires member resources to contain valid XML digital signatures
+     */
+    public static final String FEATURE_REQUIRES_SIGNATURE = ABDERA_FEATURE_BASE + "requiresSignature";
+
+    /**
+     * Indicates that the collection will add it's own digital signature to the collection feed and member resources
+     */
+    public static final String FEATURE_SIGNED_RESPONSE = ABDERA_FEATURE_BASE + "responseSignature";
+
+    /**
+     * Indicates that the collection supports the use of the Atom Bidi Attribute.
+     */
+    public static final String FEATURE_SUPPORTS_BIDI = ABDERA_FEATURE_BASE + "supportsBidi";
+
+    /**
+     * Indicates that the collection requires the use of the Atom Bidi Attribute.
+     */
+    public static final String FEATURE_REQUIRES_BIDI = ABDERA_FEATURE_BASE + "requiresBidi";
+
+    /**
+     * Indicates that the collection ignores the use of the Atom Bidi Attribute.
+     */
+    public static final String FEATURE_IGNORES_BIDI = ABDERA_FEATURE_BASE + "ignoresBidi";
+
+    /**
+     * Indicates that the collection supports the use of Geo extensions (see the org.apache.abdera.ext.geo Package)
+     */
+    public static final String FEATURE_SUPPORTS_GEO = ABDERA_FEATURE_BASE + "supportsGeo";
+
+    /**
+     * Indicates that the collection requires the use of Geo extensions (see the org.apache.abdera.ext.geo Package)
+     */
+    public static final String FEATURE_REQUIRES_GEO = ABDERA_FEATURE_BASE + "requiresGeo";
+
+    /**
+     * Indicates that the collection ignores the use of Geo extensions (see the org.apache.abdera.ext.geo Package)
+     */
+    public static final String FEATURE_IGNORES_GEO = ABDERA_FEATURE_BASE + "ignoresGeo";
+
+    /**
+     * Indicates that the collection supports the use of the Simple Sharing Extensions (see the
+     * org.apache.abdera.ext.sharing Package)
+     */
+    public static final String FEATURE_SUPPORTS_SHARING = ABDERA_FEATURE_BASE + "supportsSharing";
+
+    /**
+     * Indicates that the collection requires the use of the Simple Sharing Extensions (see the
+     * org.apache.abdera.ext.sharing Package)
+     */
+    public static final String FEATURE_REQUIRES_SHARING = ABDERA_FEATURE_BASE + "requiresSharing";
+
+    /**
+     * Indicates that the collection ignores the use of the Simple Sharing Extensions (see the
+     * org.apache.abdera.ext.sharing Package)
+     */
+    public static final String FEATURE_IGNORES_SHARING = ABDERA_FEATURE_BASE + "ignoresSharing";
+
+    /**
+     * Indicates that the collection requires the GoogleLogin auth scheme (see the org.apache.abdera.ext.gdata Package)
+     */
+    public static final String FEATURE_REQUIRES_GOOGLELOGIN = ABDERA_FEATURE_BASE + "requiresGoogleLogin";
+
+    /**
+     * Indicates that the collection supports the GoogleLogin auth scheme (see the org.apache.abdera.ext.gdata Package)
+     */
+    public static final String FEATURE_SUPPORTS_GOOGLELOGIN = ABDERA_FEATURE_BASE + "supportsGoogleLogin";
+
+    /**
+     * Indicates that the collection requires the WSSE auth scheme (see the org.apache.abdera.ext.wsse Package)
+     */
+    public static final String FEATURE_REQUIRES_WSSE = ABDERA_FEATURE_BASE + "requiresWsse";
+
+    /**
+     * Indicates that the collection supports the WSSE auth scheme (see the org.apache.abdera.ext.wsse Package)
+     */
+    public static final String FEATURE_SUPPORTS_WSSE = ABDERA_FEATURE_BASE + "supportsWsse";
+
+    /**
+     * Indicates that the collection will remove markup that is considered potentially unsafe from the entry examples of
+     * the type of markup that would be removed include scripts and embed
+     */
+    public static final String FEATURE_FILTERS_MARKUP = BLOG_FEATURE_BASE + "filtersUnsafeMarkup";
+
+    private FeaturesHelper() {
+    }
+
+    public static Features newFeatures(Abdera abdera) {
+        Factory factory = abdera.getFactory();
+        Document<Features> doc = factory.newDocument();
+        Features features = factory.newElement(FEATURES, doc);
+        doc.setRoot(features);
+        return features;
+    }
+
+    public static Features getFeaturesElement(Collection collection) {
+        return getFeaturesElement(collection, true);
+    }
+
+    public static Features getFeaturesElement(Collection collection, boolean outofline) {
+        Features features = collection.getExtension(FEATURES);
+        if (features != null && outofline) {
+            if (features.getHref() != null) {
+                String iri = features.getResolvedHref().toASCIIString();
+                Abdera abdera = collection.getFactory().getAbdera();
+                AbderaClient client = new AbderaClient(abdera);
+                try {
+                  Document<Features> doc = client.get(iri);
+                  features = doc.getRoot();
+                } catch (Throwable t) {
+                  throw new RuntimeException(t);
+                } finally {
+                  client.shutdown();
+                }
+            }
+        }
+        return features;
+    }
+
+    public static Feature getFeature(Collection collection, String feature) {
+        return getFeature(getFeaturesElement(collection), feature);
+    }
+
+    /**
+     * Returns the specified feature element or null
+     */
+    public static Feature getFeature(Features features, String feature) {
+        if (features == null)
+            return null;
+        Iterable<Feature> list = features.getExtensions(Feature.class);
+        for (Element el : list) {
+            if (el.getAttributeValue("ref").equals(feature))
+                return (Feature)el;
+        }
+        return null;
+    }
+
+    public static Status getFeatureStatus(Collection collection, String feature) {
+        return getFeatureStatus(getFeaturesElement(collection), feature);
+    }
+
+    public static Status getFeatureStatus(Features features, String feature) {
+        if (features == null)
+            return Status.UNSPECIFIED;
+        Feature f = getFeature(features, feature);
+        return f != null ? Status.SPECIFIED : Status.UNSPECIFIED;
+    }
+
+    public static Iterable<Feature> getFeatures(Collection collection) {
+        Features features = getFeaturesElement(collection);
+        if (features == null)
+            return null;
+        return features.getExtensions(FEATURE);
+    }
+
+    public static Features addFeaturesElement(Collection collection) {
+        if (getFeaturesElement(collection, false) != null)
+            throw new IllegalArgumentException(
+              "A collection element can only contain one features element");
+        return collection.addExtension(FEATURES);
+    }
+
+    /**
+     * Select a Collection from the service document
+     */
+    public static Iterable<Collection> select(Service service, Selector selector) {
+      Set<Collection> list = new LinkedHashSet<Collection>();
+      for (Workspace workspace : service.getWorkspaces()) {
+          Iterable<Collection> collections = select(workspace, selector);
+          for (Collection collection : collections)
+              list.add(collection);
+      }
+      return list;
+    }
+
+    /**
+     * Select a Collection from the service document
+     */
+    public static Iterable<Collection> select(Service service, Selector... selectors) {
+        Set<Collection> list = new LinkedHashSet<Collection>();
+        for (Workspace workspace : service.getWorkspaces()) {
+            Iterable<Collection> collections = select(workspace, selectors);
+            for (Collection collection : collections)
+                list.add(collection);
+        }
+        return list;
+    }
+
+    /**
+     * Select a Collection from the Workspace
+     */
+    public static Iterable<Collection> select(Workspace workspace, Selector selector) {
+        return workspace.getCollections(selector);
+    }
+
+    /**
+     * Select a Collection from the Workspace
+     */
+    public static Iterable<Collection> select(Workspace workspace, Selector... selectors) {
+        MultiSelector selector = new MultiSelector(selectors);
+        return workspace.getCollections(selector);
+    }
+
+}

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

Added: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/geo/GeoHelper.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/geo/GeoHelper.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/geo/GeoHelper.java (added)
+++ abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/geo/GeoHelper.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,318 @@
+/*
+ * 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.geo;
+
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.xml.namespace.QName;
+
+import org.apache.abdera2.common.Constants;
+import org.apache.abdera2.common.geo.Box;
+import org.apache.abdera2.common.geo.Coordinate;
+import org.apache.abdera2.common.geo.Line;
+import org.apache.abdera2.common.geo.Multiple;
+import org.apache.abdera2.common.geo.Point;
+import org.apache.abdera2.common.geo.Polygon;
+import org.apache.abdera2.common.geo.Position;
+import org.apache.abdera2.model.Element;
+import org.apache.abdera2.model.ExtensibleElement;
+
+/**
+ * Basic support for the GeoRSS extensions to Atom: http://georss.org/1
+ */
+public class GeoHelper {
+
+    public static final String W3C_GEO_NS = "http://www.w3.org/2003/01/geo/wgs84_pos#";
+    public static final String SIMPLE_GEO_NS = "http://www.georss.org/georss";
+    public static final String GML_NS = "http://www.opengis.net/gml";
+
+    public static final QName QNAME_W3C_POINT = new QName(W3C_GEO_NS, "Point", "geo");
+    public static final QName QNAME_W3C_LAT = new QName(W3C_GEO_NS, "lat", "geo");
+    public static final QName QNAME_W3C_LONG = new QName(W3C_GEO_NS, "long", "geo");
+
+    public static final QName QNAME_SIMPLE_POINT = new QName(SIMPLE_GEO_NS, "point", "georss");
+    public static final QName QNAME_SIMPLE_LINE = new QName(SIMPLE_GEO_NS, "line", "georss");
+    public static final QName QNAME_SIMPLE_POLYGON = new QName(SIMPLE_GEO_NS, "polygon", "georss");
+    public static final QName QNAME_SIMPLE_BOX = new QName(SIMPLE_GEO_NS, "box", "georss");
+    public static final QName QNAME_WHERE = new QName(SIMPLE_GEO_NS, "where", "georss");
+
+    public static final QName QNAME_GML_POINT = new QName(GML_NS, "Point", "gml");
+    public static final QName QNAME_GML_POS = new QName(GML_NS, "pos", "gml");
+    public static final QName QNAME_GML_LINESTRING = new QName(GML_NS, "LineString", "gml");
+    public static final QName QNAME_GML_POSLIST = new QName(GML_NS, "posList", "gml");
+    public static final QName QNAME_GML_POLYGON = new QName(GML_NS, "Polygon", "gml");
+    public static final QName QNAME_GML_EXTERIOR = new QName(GML_NS, "exterior", "gml");
+    public static final QName QNAME_GML_LINEARRING = new QName(GML_NS, "LinearRing", "gml");
+    public static final QName QNAME_GML_ENVELOPE = new QName(GML_NS, "Envelope", "gml");
+    public static final QName QNAME_GML_LOWERCORNER = new QName(GML_NS, "lowerCorner", "gml");
+    public static final QName QNAME_GML_UPPERCORNER = new QName(GML_NS, "upperCorner", "gml");
+
+    public enum Encoding {
+        SIMPLE, 
+        W3C, 
+        GML;
+        
+        public void addPosition(ExtensibleElement element, Position position) {
+          switch (this) {
+            case SIMPLE:
+                addSimplePosition(element, position);
+                break;
+            case GML:
+                addGmlPosition(element, position);
+                break;
+            case W3C:
+                addW3CPosition(element, position);
+                break;
+          }         
+        }
+    }
+
+    public static void addPosition(ExtensibleElement element, Position position) {
+        Encoding.SIMPLE.addPosition(element, position);
+    }
+
+    private static void setPositionAttributes(Element pos, Position position) {
+        if (pos != null) {
+            if (position.getFeatureTypeTag() != null)
+                pos.setAttributeValue("featuretypetag", position.getFeatureTypeTag());
+            if (position.getRelationshipTag() != null)
+                pos.setAttributeValue("relationshiptag", position.getRelationshipTag());
+            if (position.getElevation() != null)
+                pos.setAttributeValue("elev", position.getElevation().toString());
+            if (position.getFloor() != null)
+                pos.setAttributeValue("floor", position.getFloor().toString());
+            if (position.getRadius() != null)
+                pos.setAttributeValue("radius", position.getRadius().toString());
+        }
+    }
+
+    private static void addGmlPosition(ExtensibleElement element, Position position) {
+        ExtensibleElement pos = element.addExtension(QNAME_WHERE);
+        if (position instanceof Point) {
+            Point point = (Point)position;
+            ExtensibleElement p = pos.addExtension(QNAME_GML_POINT);
+            p.addSimpleExtension(QNAME_GML_POS, point.getCoordinate().toString());
+        } else if (position instanceof Line) {
+            Multiple m = (Multiple)position;
+            ExtensibleElement p = pos.addExtension(QNAME_GML_LINESTRING);
+            p.addSimpleExtension(QNAME_GML_POSLIST, m.getCoordinates().toString());
+        } else if (position instanceof Polygon) {
+            Multiple m = (Multiple)position;
+            ExtensibleElement p = pos.addExtension(QNAME_GML_POLYGON);
+            p = p.addExtension(QNAME_GML_EXTERIOR);
+            p = p.addExtension(QNAME_GML_LINEARRING);
+            p.addSimpleExtension(QNAME_GML_POSLIST, m.getCoordinates().toString());
+        } else if (position instanceof Box) {
+            Box m = (Box)position;
+            ExtensibleElement p = pos.addExtension(QNAME_GML_ENVELOPE);
+            if (m.getLowerCorner() != null)
+                p.addSimpleExtension(QNAME_GML_LOWERCORNER, m.getLowerCorner().toString());
+            if (m.getUpperCorner() != null)
+                p.addSimpleExtension(QNAME_GML_UPPERCORNER, m.getUpperCorner().toString());
+        }
+        setPositionAttributes(pos, position);
+    }
+
+    private static void addSimplePosition(ExtensibleElement element, Position position) {
+        Element pos = null;
+        if (position instanceof Point) {
+            Point point = (Point)position;
+            pos = element.addSimpleExtension(QNAME_SIMPLE_POINT, point.getCoordinate().toString());
+        } else if (position instanceof Multiple) {
+            Multiple line = (Multiple)position;
+            QName qname =
+                position instanceof Line ? QNAME_SIMPLE_LINE : position instanceof Box ? QNAME_SIMPLE_BOX
+                    : position instanceof Polygon ? QNAME_SIMPLE_POLYGON : null;
+            if (qname != null) {
+                pos = element.addSimpleExtension(qname, line.getCoordinates().toString());
+            }
+        }
+        setPositionAttributes(pos, position);
+    }
+
+    private static void addW3CPosition(ExtensibleElement element, Position position) {
+        if (!(position instanceof Point))
+            throw new IllegalArgumentException("The W3C Encoding only supports Points");
+        Element el = element.getExtension(QNAME_W3C_LAT);
+        if (el != null)
+            el.discard();
+        el = element.getExtension(QNAME_W3C_LONG);
+        if (el != null)
+            el.discard();
+        Point point = (Point)position;
+
+        ExtensibleElement p = element.addExtension(QNAME_W3C_POINT);
+        p.addSimpleExtension(QNAME_W3C_LAT, Double.toString(point.getCoordinate().getLatitude()));
+        p.addSimpleExtension(QNAME_W3C_LONG, Double.toString(point.getCoordinate().getLongitude()));
+
+    }
+
+    private static Iterable<Position> _getPositions(ExtensibleElement element) {
+        Set<Position> list = new LinkedHashSet<Position>();
+        getW3CPosition(element, list);
+        getSimplePosition(element, list);
+        getGMLPosition(element, list);
+        return list;
+    }
+
+    public static boolean isGeotagged(ExtensibleElement element) {
+        if (element.getExtensions(QNAME_SIMPLE_POINT).size() > 0)
+            return true;
+        if (element.getExtensions(QNAME_SIMPLE_LINE).size() > 0)
+            return true;
+        if (element.getExtensions(QNAME_SIMPLE_BOX).size() > 0)
+            return true;
+        if (element.getExtensions(QNAME_SIMPLE_POLYGON).size() > 0)
+            return true;
+        if (element.getExtensions(QNAME_WHERE).size() > 0)
+            return true;
+        if (element.getExtensions(QNAME_W3C_POINT).size() > 0)
+            return true;
+        if (element.getExtensions(QNAME_W3C_LAT).size() > 0 && element.getExtensions(QNAME_W3C_LONG).size() > 0)
+            return true;
+        return false;
+    }
+
+    public static Iterator<Position> listPositions(ExtensibleElement element) {
+        return _getPositions(element).iterator();
+    }
+
+    public static Position getAsPosition(Element element) {
+        Position pos = null;
+        QName qname = element.getQName();
+        String text = element.getText();
+        if (qname.equals(QNAME_GML_POINT)) {
+            element = traverse((ExtensibleElement)element, QNAME_GML_POS);
+            if (element != null && text != null) {
+                pos = new Point(text.trim());
+            }
+        } else if (qname.equals(QNAME_GML_LINESTRING)) {
+            element = traverse((ExtensibleElement)element, QNAME_GML_POSLIST);
+            if (element != null && text != null) {
+                pos = new Line(text.trim());
+            }
+        } else if (qname.equals(QNAME_GML_POLYGON)) {
+            element = traverse((ExtensibleElement)element, QNAME_GML_EXTERIOR, QNAME_GML_LINEARRING, QNAME_GML_POSLIST);
+            if (element != null && text != null) {
+                pos = new Polygon(text.trim());
+            }
+        } else if (qname.equals(QNAME_GML_ENVELOPE)) {
+            String lc = ((ExtensibleElement)element).getSimpleExtension(QNAME_GML_LOWERCORNER);
+            String uc = ((ExtensibleElement)element).getSimpleExtension(QNAME_GML_UPPERCORNER);
+            if (lc != null && uc != null) {
+                Coordinate c1 = new Coordinate(lc);
+                Coordinate c2 = new Coordinate(uc);
+                pos = new Box(c1, c2);
+            }
+        } else if (qname.equals(QNAME_SIMPLE_POINT) && text != null) {
+            pos = new Point(text.trim());
+        } else if (qname.equals(QNAME_SIMPLE_LINE) && text != null) {
+            pos = new Line(text.trim());
+        } else if (qname.equals(QNAME_SIMPLE_BOX) && text != null) {
+            pos = new Box(text.trim());
+        } else if (qname.equals(QNAME_SIMPLE_POLYGON) && text != null) {
+            pos = new Polygon(text.trim());
+        } else if (qname.equals(QNAME_W3C_POINT) || qname.equals(Constants.ENTRY)) {
+            Set<Position> list = new LinkedHashSet<Position>();
+            getW3CPosition((ExtensibleElement)element, list);
+            for (Position p : list) {
+              pos = p; 
+              break;
+            }
+        }
+        return pos;
+    }
+
+    public static Iterable<Position> getPositions(ExtensibleElement element) {
+        return _getPositions(element);
+    }
+
+    private static void getSimplePosition(ExtensibleElement element, Set<Position> list) {
+        Iterable<Element> elements = element.getExtensions(SIMPLE_GEO_NS);
+        for (Element el : elements) {
+            Position pos = getAsPosition(el);
+            if (pos != null) {
+                getPositionAttributes(el, pos);
+                list.add(pos);
+            }
+        }
+    }
+
+    private static void getGMLPosition(ExtensibleElement element, Set<Position> list) {
+        Iterable<ExtensibleElement> elements = element.getExtensions(QNAME_WHERE);
+        for (ExtensibleElement where : elements) {
+            Position pos = null;
+            List<ExtensibleElement> children = where.getElements();
+            for (ExtensibleElement el : children) {
+                pos = getAsPosition(el);
+                if (pos != null) {
+                    getPositionAttributes(el, pos);
+                    list.add(pos);
+                }
+            }
+        }
+    }
+
+    private static ExtensibleElement traverse(ExtensibleElement element, QName... qnames) {
+        for (QName qname : qnames) {
+            element = element.getExtension(qname);
+            if (element == null)
+                break;
+        }
+        return element;
+    }
+
+    private static void getPositionAttributes(Element pos, Position position) {
+        if (position != null) {
+            String featuretypetag = pos.getAttributeValue("featuretypetag");
+            String relationshiptag = pos.getAttributeValue("relationshiptag");
+            String elevation = pos.getAttributeValue("elev");
+            String floor = pos.getAttributeValue("floor");
+            String radius = pos.getAttributeValue("radius");
+            if (featuretypetag != null)
+                position.setFeatureTypeTag(featuretypetag);
+            if (featuretypetag != null)
+                position.setRelationshipTag(relationshiptag);
+            if (elevation != null)
+                position.setElevation(Double.valueOf(elevation));
+            if (floor != null)
+                position.setFloor(Double.valueOf(floor));
+            if (radius != null)
+                position.setRadius(Double.valueOf(radius));
+        }
+    }
+
+    private static void getW3CPosition(ExtensibleElement element, Set<Position> list) {
+        getSimpleW3CPosition(element, list);
+        List<ExtensibleElement> points = element.getExtensions(QNAME_W3C_POINT);
+        for (ExtensibleElement point : points)
+            getSimpleW3CPosition(point, list);
+    }
+
+    private static void getSimpleW3CPosition(ExtensibleElement el, Set<Position> list) {
+        String slat = el.getSimpleExtension(QNAME_W3C_LAT);
+        String slong = el.getSimpleExtension(QNAME_W3C_LONG);
+        if (slat != null && slong != null) {
+            Point point = new Point(slat.trim() + " " + slong.trim());
+            list.add(point);
+        }
+    }
+}

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



Mime
View raw message