abdera-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jmsn...@apache.org
Subject svn commit: r1239237 [7/12] - in /abdera/abdera2-server: ./ .settings/ etc/ examples/ examples/src/ examples/src/main/ examples/src/main/java/ examples/src/main/java/org/ examples/src/main/java/org/apache/ examples/src/main/java/org/apache/abdera2/ exa...
Date Wed, 01 Feb 2012 17:55:02 GMT
Added: abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/context/EntityProviderResponseContext.java
URL: http://svn.apache.org/viewvc/abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/context/EntityProviderResponseContext.java?rev=1239237&view=auto
==============================================================================
--- abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/context/EntityProviderResponseContext.java (added)
+++ abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/context/EntityProviderResponseContext.java Wed Feb  1 17:54:54 2012
@@ -0,0 +1,72 @@
+/*
+ * 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.protocol.server.context;
+
+import java.io.IOException;
+
+import org.apache.abdera2.Abdera;
+import org.apache.abdera2.protocol.EntityProvider;
+import org.apache.abdera2.writer.StreamWriter;
+
+/**
+ * StreamWriterResponseContext implementation based on the EntityProvider interface
+ */
+public class EntityProviderResponseContext 
+  extends StreamWriterResponseContext {
+
+    private final EntityProvider provider;
+
+    public EntityProviderResponseContext(
+      EntityProvider provider, 
+      Abdera abdera, 
+      String encoding, 
+      String sw) {
+        super(abdera, encoding, sw);
+        this.provider = provider;
+        init();
+    }
+
+    public EntityProviderResponseContext(
+      EntityProvider provider, 
+      Abdera abdera, 
+      String encoding) {
+        super(abdera, encoding);
+        this.provider = provider;
+        init();
+    }
+
+    public EntityProviderResponseContext(
+      EntityProvider provider, 
+      Abdera abdera) {
+        super(abdera);
+        this.provider = provider;
+        init();
+    }
+
+    private void init() {
+        setContentType(provider.getContentType());
+        setEntityTag(provider.getEntityTag());
+        setLastModified(provider.getLastModified());
+    }
+
+    @Override
+    protected void writeTo(StreamWriter sw) throws IOException {
+        provider.writeTo(sw);
+    }
+
+}

Propchange: abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/context/EntityProviderResponseContext.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/context/FOMResponseContext.java
URL: http://svn.apache.org/viewvc/abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/context/FOMResponseContext.java?rev=1239237&view=auto
==============================================================================
--- abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/context/FOMResponseContext.java (added)
+++ abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/context/FOMResponseContext.java Wed Feb  1 17:54:54 2012
@@ -0,0 +1,145 @@
+/*
+ * 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.protocol.server.context;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import javax.activation.MimeType;
+
+import org.apache.abdera2.model.Base;
+import org.apache.abdera2.model.Document;
+import org.apache.abdera2.model.Element;
+import org.apache.abdera2.model.Element.Helper;
+import org.apache.abdera2.protocol.server.AtompubResponseContext;
+import org.apache.abdera2.common.mediatype.MimeTypeHelper;
+import org.apache.abdera2.common.protocol.AbstractResponseContext;
+import org.apache.abdera2.writer.Writer;
+
+public class FOMResponseContext<T extends Base> 
+    extends AbstractResponseContext 
+            implements AtompubResponseContext {
+
+    private final T base;
+    private final boolean chunked;
+
+    protected Writer writer;
+    
+    public FOMResponseContext(T base) {
+        this(base, true);
+    }
+
+    public FOMResponseContext(T base, boolean chunked) {
+        this.base = base;
+        setStatus(200);
+        setStatusText("OK");
+        this.chunked = chunked;
+        try {
+            MimeType type = getContentType();
+            String charset = 
+              type.getParameter("charset");
+            if (charset == null)
+                charset = getCharsetFromBase(base);
+            if (charset == null)
+                charset = "UTF-8";
+            type.setParameter("charset", charset);
+            setContentType(type.toString());
+        } catch (Exception e) {
+        }
+    }
+
+    private String getCharsetFromBase(Base base) {
+      return base == null ?
+        null :
+        base instanceof Document ?
+          ((Document<?>)base).getCharset() :
+          base instanceof Element ?
+              getCharsetFromBase(((Element)base).getDocument()) :
+              null;
+    }
+
+    public T getBase() {
+      return base;
+    }
+
+    public boolean hasEntity() {
+      return (base != null);
+    }
+
+    public void writeTo(java.io.Writer javaWriter) throws IOException {
+      if (hasEntity())
+        if (writer == null)
+          base.writeTo(javaWriter);
+        else
+          writeTo(javaWriter, writer);
+    }
+
+    public void writeTo(OutputStream out) throws IOException {
+      if (hasEntity())
+        if (writer == null)
+          base.writeTo(out);
+        else
+          writeTo(out, writer);
+    }
+
+    @Override
+    public MimeType getContentType() {
+      MimeType t = super.getContentType();
+      if (t == null) {
+        String type = Helper.getMimeType(base);
+        if (type != null)
+          t = MimeTypeHelper.create(type);
+      }
+      return t;
+    }
+
+    @Override
+    public long getContentLength() {
+      long len = super.getContentLength();
+      if (hasEntity() && len == -1 && !chunked) {
+        try {
+          ByteArrayOutputStream out = 
+            new ByteArrayOutputStream();
+          base.writeTo(out);
+          len = out.size();
+          super.setContentLength(len);
+        } catch (Exception e) {}
+      }
+      return len;
+    }
+
+    public void writeTo(
+      OutputStream out, 
+      Writer writer) 
+        throws IOException {
+      writer.writeTo(base, out);
+    }
+
+    public void writeTo(
+      java.io.Writer javaWriter, 
+      Writer abderaWriter) 
+        throws IOException {
+      abderaWriter.writeTo(base, javaWriter);
+    }
+    
+    public AtompubResponseContext setWriter(Writer writer) {
+      this.writer = writer;
+      return this;
+    }
+}

Propchange: abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/context/FOMResponseContext.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/context/ResponseContextWrapper.java
URL: http://svn.apache.org/viewvc/abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/context/ResponseContextWrapper.java?rev=1239237&view=auto
==============================================================================
--- abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/context/ResponseContextWrapper.java (added)
+++ abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/context/ResponseContextWrapper.java Wed Feb  1 17:54:54 2012
@@ -0,0 +1,60 @@
+/*
+ * 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.protocol.server.context;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import org.apache.abdera2.common.protocol.BaseResponseContextWrapper;
+import org.apache.abdera2.protocol.server.AtompubResponseContext;
+import org.apache.abdera2.writer.Writer;
+
+public class ResponseContextWrapper 
+  extends BaseResponseContextWrapper 
+  implements AtompubResponseContext {
+
+    public ResponseContextWrapper(
+      AtompubResponseContext response) {
+        super(response);
+    }
+
+    private AtompubResponseContext getResponse() {
+      return (AtompubResponseContext)response;
+    }
+    
+    public AtompubResponseContext setWriter(
+      Writer writer) {
+        getResponse().setWriter(writer);
+        return this;
+    }
+
+    public void writeTo(
+      OutputStream out, 
+      Writer writer) 
+        throws IOException {
+      getResponse().writeTo(out, writer);
+    }
+
+    public void writeTo(
+      java.io.Writer javaWriter, 
+      Writer abderaWriter) 
+        throws IOException {
+      getResponse().writeTo(
+        javaWriter, 
+        abderaWriter);
+    }
+}

Propchange: abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/context/ResponseContextWrapper.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/context/StreamWriterResponseContext.java
URL: http://svn.apache.org/viewvc/abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/context/StreamWriterResponseContext.java?rev=1239237&view=auto
==============================================================================
--- abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/context/StreamWriterResponseContext.java (added)
+++ abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/context/StreamWriterResponseContext.java Wed Feb  1 17:54:54 2012
@@ -0,0 +1,129 @@
+/*
+ * 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.protocol.server.context;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+
+import org.apache.abdera2.Abdera;
+import org.apache.abdera2.common.protocol.SimpleResponseContext;
+import org.apache.abdera2.protocol.server.AtompubResponseContext;
+import org.apache.abdera2.writer.StreamWriter;
+
+/**
+ * Abstract base class for creating ResponseContext implementations that use the StreamWriter interface. Using the
+ * StreamWriter to write out documents is significantly faster than using the object model but requires developers to
+ * know more about proper Atom syntax.
+ */
+public abstract class StreamWriterResponseContext 
+  extends SimpleResponseContext
+  implements AtompubResponseContext {
+
+    private final Abdera abdera;
+    private final String sw;
+    private boolean autoindent;
+
+    /**
+     * Create a new StreamWriterResponseContext
+     * 
+     * @param abdera The Abdera instance
+     */
+    protected StreamWriterResponseContext(Abdera abdera) {
+        this(abdera, null, null);
+    }
+
+    /**
+     * Create a new StreamWriterResponseContext
+     * 
+     * @param abdera The Abdera instance
+     * @param encoding The charset encoding
+     */
+    protected StreamWriterResponseContext(Abdera abdera, String encoding) {
+        this(abdera, encoding, null);
+    }
+
+    /**
+     * Create a new StreamWriterResponseContext
+     * 
+     * @param abdera The Abdera instance
+     * @param encoding The charset encoding
+     * @param sw The name of the Named StreamWriter to use
+     */
+    protected StreamWriterResponseContext(Abdera abdera, String encoding, String sw) {
+        super(encoding);
+        this.abdera = abdera!=null?abdera:Abdera.getInstance();
+        this.sw = sw;
+    }
+
+    /**
+     * Get the Abdera instance
+     */
+    protected final Abdera getAbdera() {
+        return abdera;
+    }
+
+    /**
+     * Create a new StreamWriter instance. If the sw property was set, the specified Named StreamWriter will be returned
+     */
+    protected StreamWriter newStreamWriter() {
+        return sw == null ? abdera.create(StreamWriter.class) : 
+          abdera.getWriterFactory().newStreamWriter(sw);
+    }
+
+    protected void writeEntity(Writer writer) throws IOException {
+        writeTo(newStreamWriter().setWriter(writer).setAutoIndent(autoindent));
+    }
+
+    /**
+     * Write to the specified StreamWriter. Subclasses of this class must implement this method.
+     */
+    protected abstract void writeTo(StreamWriter sw) throws IOException;
+
+    /**
+     * True to enable automatic indenting on the StreamWriter
+     */
+    public StreamWriterResponseContext setAutoIndent(boolean autoindent) {
+        this.autoindent = autoindent;
+        return this;
+    }
+
+    /**
+     * True if automatic indenting is enabled on the StreamWriter
+     */
+    public boolean getAutoIndent() {
+        return this.autoindent;
+    }
+
+    public boolean hasEntity() {
+        return true;
+    }
+
+    public AtompubResponseContext setWriter(
+        org.apache.abdera2.writer.Writer writer) {
+      throw new UnsupportedOperationException();
+    }
+
+    public void writeTo(OutputStream out, org.apache.abdera2.writer.Writer writer) throws IOException {
+      throw new UnsupportedOperationException();
+    }
+
+    public void writeTo(Writer javaWriter, org.apache.abdera2.writer.Writer abderaWriter) throws IOException {
+      throw new UnsupportedOperationException();
+    }
+}

Propchange: abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/context/StreamWriterResponseContext.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubCollectionAdapter.java
URL: http://svn.apache.org/viewvc/abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubCollectionAdapter.java?rev=1239237&view=auto
==============================================================================
--- abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubCollectionAdapter.java (added)
+++ abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubCollectionAdapter.java Wed Feb  1 17:54:54 2012
@@ -0,0 +1,152 @@
+/*
+ * 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.protocol.server.impl;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.apache.abdera2.Abdera;
+import org.apache.abdera2.factory.Factory;
+import org.apache.abdera2.common.protocol.AbstractCollectionAdapter;
+import org.apache.abdera2.common.protocol.ProviderHelper;
+import org.apache.abdera2.common.protocol.RequestContext;
+import org.apache.abdera2.common.protocol.ResponseContext;
+import org.apache.abdera2.common.protocol.ResponseContextException;
+import org.apache.abdera2.model.Collection;
+import org.apache.abdera2.model.Document;
+import org.apache.abdera2.model.Entry;
+import org.apache.abdera2.model.Feed;
+import org.apache.abdera2.parser.ParseException;
+import org.apache.abdera2.parser.Parser;
+import org.apache.abdera2.protocol.server.context.FOMResponseContext;
+import org.apache.abdera2.protocol.server.model.AtompubCategoriesInfo;
+import org.apache.abdera2.protocol.server.model.AtompubCollectionInfo;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+
+/**
+ * Base CollectionAdapter implementation that provides a number of helper utility methods for adapter implementations.
+ */
+public abstract class AbstractAtompubCollectionAdapter 
+  extends AbstractCollectionAdapter
+  implements AtompubCollectionInfo {
+
+    public AbstractAtompubCollectionAdapter(String href) {
+    super(href);
+  }
+
+    public Iterable<String> getAccepts(RequestContext request) {
+      return Arrays.<String>asList("application/atom+xml;type=entry");
+    }
+    
+    public Iterable<AtompubCategoriesInfo> getCategoriesInfo(RequestContext request) {
+      return Collections.<AtompubCategoriesInfo>emptySet();
+    }
+    
+    /**
+     * Creates the ResponseContext for a newly created entry. By default, a BaseResponseContext is returned. The
+     * Location, Content-Location, Etag and status are set appropriately.
+     */
+    protected ResponseContext buildCreateEntryResponse(String link, Entry entry) {
+        return new FOMResponseContext<Entry>(entry)
+          .setLocation(link)
+          .setContentLocation(link)
+          .setEntityTag(AbstractAtompubProvider.calculateEntityTag(entry))
+          .setStatus(201);
+    }
+
+    /**
+     * Creates the ResponseContext for a newly created entry. By default, a BaseResponseContext is returned. The
+     * Location, Content-Location, Etag and status are set appropriately.
+     */
+    protected ResponseContext buildPostMediaEntryResponse(String link, Entry entry) {
+      return buildCreateEntryResponse(link, entry);
+    }
+
+    /**
+     * Creates the ResponseContext for a GET entry request. By default, a BaseResponseContext is returned. The Entry
+     * will contain an appropriate atom:source element and the Etag header will be set.
+     */
+    protected ResponseContext buildGetEntryResponse(RequestContext request, Entry entry)
+        throws ResponseContextException {
+        Feed feed = createFeedBase(request);
+        entry.setSource(feed.getAsSource());
+        Document<Entry> entry_doc = entry.getDocument();
+        return new FOMResponseContext<Document<Entry>>(entry_doc)
+          .setEntityTag(AbstractAtompubProvider.calculateEntityTag(entry));
+    }
+
+    /**
+     * Creates the ResponseContext for a GET feed request. By default, a BaseResponseContext is returned. The Etag
+     * header will be set.
+     */
+    protected ResponseContext buildGetFeedResponse(Feed feed) {
+        Document<Feed> document = feed.getDocument();
+        return new FOMResponseContext<Document<Feed>>(document)
+          .setEntityTag(AbstractAtompubProvider.calculateEntityTag(document.getRoot()));
+    }
+
+    /**
+     * Create the base feed for the requested collection.
+     */
+    protected Feed createFeedBase(RequestContext request) throws ResponseContextException {
+        Factory factory = AbstractAtompubProvider.getAbdera(request).getFactory();
+        Feed feed = factory.newFeed();
+        feed.setId(getId(request));
+        feed.setTitle(getTitle(request));
+        feed.addLink("");
+        feed.addLink("", "self");
+        feed.addAuthor(getAuthor(request));
+        feed.setUpdatedNow();
+        return feed;
+    }
+
+    /**
+     * Retrieves the FOM Entry object from the request payload.
+     */
+    protected Entry getEntryFromRequest(RequestContext request) throws ResponseContextException {
+        Abdera abdera = AbstractAtompubProvider.getAbdera(request);
+        Parser parser = abdera.getParser();
+
+        Document<Entry> entry_doc;
+        try {
+          entry_doc = AbstractAtompubProvider.getDocument(parser,request);
+        } catch (ParseException e) {
+          throw new ResponseContextException(400, e);
+        } catch (Throwable t) {
+          throw new ResponseContextException(500, t);
+        }
+        return entry_doc == null ? null : entry_doc.getRoot();
+    }
+
+    public Collection asCollectionElement(RequestContext request) {
+        Collection collection = AbstractAtompubProvider.getAbdera(request).getFactory().newCollection();
+        collection.setHref(getHref(request));
+        collection.setTitle(getTitle(request));
+        collection.setAccept(getAccepts(request));
+        for (AtompubCategoriesInfo catsinfo : getCategoriesInfo(request)) {
+            collection.addCategories(catsinfo.asCategoriesElement(request));
+        }
+        return collection;
+    }
+    
+    public Predicate<RequestContext> acceptable() {
+      return Predicates.or(super.acceptable(),ProviderHelper.isAtom());
+    }
+}

Propchange: abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubCollectionAdapter.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubCollectionAdapter.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubProvider.java
URL: http://svn.apache.org/viewvc/abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubProvider.java?rev=1239237&view=auto
==============================================================================
--- abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubProvider.java (added)
+++ abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubProvider.java Wed Feb  1 17:54:54 2012
@@ -0,0 +1,316 @@
+/*
+ * 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.protocol.server.impl;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import javax.activation.MimeType;
+
+import org.apache.abdera2.Abdera;
+import org.apache.abdera2.common.Constants;
+import org.apache.abdera2.common.Localizer;
+import org.apache.abdera2.common.date.DateTimes;
+import org.apache.abdera2.common.http.EntityTag;
+import org.apache.abdera2.common.http.QualityHelper;
+import org.apache.abdera2.common.http.QualityHelper.QToken;
+import org.apache.abdera2.common.mediatype.MimeTypeHelper;
+import org.apache.abdera2.common.misc.ExceptionHelper;
+import org.apache.abdera2.common.protocol.AbstractProvider;
+import org.apache.abdera2.common.protocol.CollectionRequestProcessor;
+import org.apache.abdera2.common.protocol.EntryRequestProcessor;
+import org.apache.abdera2.common.protocol.MediaRequestProcessor;
+import org.apache.abdera2.common.protocol.RequestContext;
+import org.apache.abdera2.common.protocol.RequestContext.Scope;
+import org.apache.abdera2.common.protocol.ResponseContext;
+import org.apache.abdera2.common.protocol.Provider;
+import org.apache.abdera2.common.protocol.ProviderHelper;
+import org.apache.abdera2.common.protocol.TargetType;
+import org.apache.abdera2.common.protocol.WorkspaceInfo;
+import org.apache.abdera2.common.protocol.WorkspaceManager;
+import org.apache.abdera2.model.Base;
+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.model.Link;
+import org.apache.abdera2.model.Service;
+import org.apache.abdera2.parser.ParseException;
+import org.apache.abdera2.parser.Parser;
+import org.apache.abdera2.parser.ParserOptions;
+import org.apache.abdera2.protocol.error.Error;
+import org.apache.abdera2.protocol.server.AtompubProvider;
+import org.apache.abdera2.protocol.server.AtompubResponseContext;
+import org.apache.abdera2.protocol.server.context.FOMResponseContext;
+import org.apache.abdera2.protocol.server.context.StreamWriterResponseContext;
+import org.apache.abdera2.protocol.server.model.AtompubWorkspaceInfo;
+import org.apache.abdera2.protocol.server.processors.CategoriesRequestProcessor;
+import org.apache.abdera2.protocol.server.processors.ServiceRequestProcessor;
+import org.apache.abdera2.writer.StreamWriter;
+import org.apache.abdera2.writer.Writer;
+import org.apache.abdera2.writer.WriterFactory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.joda.time.DateTime;
+
+import com.google.common.base.Predicate;
+
+/**
+ * Base Provider implementation that provides the core implementation details for all Providers. This class provides the
+ * basic request routing logic.
+ */
+public abstract class AbstractAtompubProvider 
+  extends AbstractProvider
+  implements AtompubProvider {
+
+    private final static Log log = LogFactory.getLog(AbstractAtompubProvider.class);
+    protected Abdera abdera;
+    protected WorkspaceManager workspaceManager;
+    public static final Predicate<RequestContext> IS_ATOM = 
+      new Predicate<RequestContext>() {
+        public boolean apply(RequestContext input) {
+          MimeType ct = input.getContentType();
+          if (ct == null) return false;
+          return MimeTypeHelper.isAtom(ct.toString());
+        }
+    };
+
+    protected AbstractAtompubProvider(
+      WorkspaceManager workspaceManager) {
+      this.workspaceManager = workspaceManager;
+      addRequestProcessor(
+        TargetType.TYPE_SERVICE, 
+        ServiceRequestProcessor.class, 
+        workspaceManager);
+      addRequestProcessor(
+        TargetType.TYPE_CATEGORIES, 
+        CategoriesRequestProcessor.class,
+        workspaceManager);
+      addRequestProcessor(
+        TargetType.TYPE_COLLECTION, 
+        CollectionRequestProcessor.class,
+        ProviderHelper.isAtom(),        
+        workspaceManager);
+      addRequestProcessor(
+        TargetType.TYPE_ENTRY,
+        EntryRequestProcessor.class,
+        workspaceManager);
+      addRequestProcessor(
+        TargetType.TYPE_MEDIA, 
+        MediaRequestProcessor.class, 
+        workspaceManager);
+    }
+
+    public void init(Map<String, Object> properties) {
+      this.abdera = 
+        properties != null && 
+        properties.containsKey("abdera") ?
+          (Abdera)properties.get("abdera") :
+          Abdera.getInstance();
+      super.init(properties);
+    }
+
+    public Abdera getAbdera() {
+        return abdera;
+    }
+
+    protected Service getServiceElement(RequestContext request) {
+        Service service = abdera.newService();
+        for (WorkspaceInfo wi : getWorkspaceManager().getWorkspaces(request)) {
+            if (wi instanceof AtompubWorkspaceInfo) {
+              AtompubWorkspaceInfo awi = (AtompubWorkspaceInfo) wi;
+              service.addWorkspace(awi.asWorkspaceElement(request));
+            }
+        }
+        return service;
+    }
+    
+    public WorkspaceManager getWorkspaceManager() {
+      return workspaceManager;
+  }
+    
+    public ResponseContext createErrorResponse(int code, String message, Throwable t) {
+      return createErrorResponse(abdera,code,message,t);
+    }
+    
+    public static Abdera getAbdera(RequestContext context) {
+      Provider provider = context.getProvider();
+      return provider instanceof AtompubProvider ? 
+        ((AtompubProvider)provider).getAbdera() : 
+        Abdera.getInstance();
+    }
+
+    public static ResponseContext createErrorResponse(
+        Abdera abdera,
+        final int code, 
+        final String message,
+        final Throwable t) {
+        return
+          new StreamWriterResponseContext(abdera) {
+            protected void writeTo(StreamWriter sw) throws IOException {
+              Error.create(sw, code, message, t);
+            }
+          }
+          .setStatus(code)
+          .setStatusText(message);
+      }
+
+    /**
+     * Returns an appropriate NamedWriter instance given an appropriately formatted HTTP Accept header. The header will
+     * be parsed and sorted according to it's q parameter values. The first named writer capable of supporting the
+     * specified type, in order of q-value preference, will be returned. The results on this are not always predictable.
+     * For instance, if the Accept header says "application/*" it could end up with either the JSON writer or the
+     * PrettyXML writer, or any other writer that supports any writer that supports a specific form of "application/*".
+     * It's always best to be very specific in the Accept headers.
+     */
+    public static Writer getAcceptableNamedWriter(Abdera abdera, String accept_header) {
+      QToken[] sorted_accepts = QualityHelper.orderByQ(accept_header);
+      WriterFactory factory = abdera.getWriterFactory();
+      if (factory == null)
+          return null;
+      for (QToken accept : sorted_accepts) {
+          Writer writer = factory.getWriterByMediaType(accept.token());
+          if (writer != null)
+              return writer;
+      }
+      return null;
+    }
+
+    public static Writer getNamedWriter(Abdera abdera, String mediatype) {
+        WriterFactory factory = abdera.getWriterFactory();
+        if (factory == null)
+            return null;
+        Writer writer = factory.getWriterByMediaType(mediatype);
+        return writer;
+    }
+
+    public static EntityTag calculateEntityTag(Base base) {
+        String id = null;
+        String modified = null;
+        if (base instanceof Entry) {
+          Entry entry = (Entry)base;
+          id = entry.getId().toString();
+          modified = 
+            DateTimes.format(
+              entry.getEdited() != null ? 
+                entry.getEdited() : 
+                entry.getUpdated());
+        } else if (base instanceof Feed) {
+            Feed feed = (Feed)base;
+            id = feed.getId().toString();
+            modified = DateTimes.format(feed.getUpdated());
+        } else if (base instanceof Document) {
+            return calculateEntityTag(((Document<?>)base).getRoot());
+        }
+        return EntityTag.generate(id, modified);
+    }
+
+    public static String getEditUriFromEntry(Entry entry) {
+        String editUri = null;
+        List<Link> editLinks = entry.getLinks("edit");
+        if (editLinks != null) {
+            for (Link link : editLinks) {
+                // if there is more than one edit link, we should not automatically
+                // assume that it's always going to point to an Atom document
+                // representation.
+                if (link.getMimeType() != null) {
+                    if (MimeTypeHelper.isMatch(link.getMimeType().toString(), Constants.ATOM_MEDIA_TYPE)) {
+                        editUri = link.getResolvedHref().toString();
+                        break;
+                    }
+                } else {
+                    // edit link with no type attribute is the right one to use
+                    editUri = link.getResolvedHref().toString();
+                    break;
+                }
+            }
+        }
+        return editUri;
+    }
+
+    /**
+     * Return a document
+     */
+    public static AtompubResponseContext returnBase(Base base, int status, DateTime lastModified) {
+        log.debug(Localizer.get("RETURNING.DOCUMENT"));
+        FOMResponseContext<Base> response = new FOMResponseContext<Base>(base);
+        response.setStatus(status);
+        if (lastModified != null)
+            response.setLastModified(lastModified);
+        // response.setContentType(MimeTypeHelper.getMimeType(base));
+        Document<?> doc = base instanceof Document ? (Document<?>)base : ((Element)base).getDocument();
+        if (doc.getEntityTag() != null) {
+            response.setEntityTag(doc.getEntityTag());
+        } else if (doc.getLastModified() != null) {
+            response.setLastModified(doc.getLastModified());
+        }
+        return response;
+    }
+    
+    public static <T extends Element>Document<T> getDocument(
+      RequestContext context)
+        throws ParseException, IOException {
+      return getDocument(null, null, context);
+    }
+
+    public static <T extends Element> Document<T> getDocument(
+      Parser parser, RequestContext context) 
+        throws ParseException, IOException {
+      return getDocument(parser,null,context);
+    }
+
+    public static <T extends Element> Document<T> getDocument(
+      ParserOptions options, 
+      RequestContext context) throws ParseException,
+        IOException {
+        return getDocument(null,options,context);
+    }
+
+    public static <T extends Element> Document<T> getDocument(
+      Parser parser, 
+      ParserOptions options, 
+      RequestContext context)
+        throws ParseException, IOException {
+      
+      Document<T> doc = context.getAttribute(Scope.REQUEST, Document.class.getName());
+      if (doc == null) {
+        try {
+          AtompubProvider provider = context.<AtompubProvider>getProvider();
+          Abdera abdera = provider.getAbdera();
+          log.debug(Localizer.get("PARSING.REQUEST.DOCUMENT"));
+          if (parser == null)
+              parser = abdera.getParser();
+          if (parser == null)
+              throw new IllegalArgumentException(
+                "No Parser implementation was provided");
+          if (options == null)
+            options = parser.getDefaultParserOptions();
+          doc = parser.parse(
+            context.getInputStream(), 
+            context.getResolvedUri().toString(), 
+            options);
+          context.setAttribute(Document.class.getName(), doc);
+        } catch (Throwable t) {
+          throw ExceptionHelper.propogate(t);
+        }
+      }
+      return doc;
+    }
+
+}

Propchange: abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubProvider.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubWorkspaceProvider.java
URL: http://svn.apache.org/viewvc/abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubWorkspaceProvider.java?rev=1239237&view=auto
==============================================================================
--- abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubWorkspaceProvider.java (added)
+++ abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubWorkspaceProvider.java Wed Feb  1 17:54:54 2012
@@ -0,0 +1,83 @@
+/*
+ * 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.protocol.server.impl;
+
+import java.util.Map;
+
+import org.apache.abdera2.Abdera;
+import org.apache.abdera2.common.protocol.AbstractWorkspaceProvider;
+import org.apache.abdera2.common.protocol.CollectionRequestProcessor;
+import org.apache.abdera2.common.protocol.EntryRequestProcessor;
+import org.apache.abdera2.common.protocol.MediaRequestProcessor;
+import org.apache.abdera2.common.protocol.ProviderHelper;
+import org.apache.abdera2.common.protocol.ResponseContext;
+import org.apache.abdera2.common.protocol.TargetType;
+import org.apache.abdera2.common.protocol.WorkspaceManager;
+import org.apache.abdera2.protocol.server.AtompubProvider;
+import org.apache.abdera2.protocol.server.processors.CategoriesRequestProcessor;
+import org.apache.abdera2.protocol.server.processors.ServiceRequestProcessor;
+
+public abstract class AbstractAtompubWorkspaceProvider 
+  extends AbstractWorkspaceProvider
+  implements AtompubProvider, 
+             WorkspaceManager {
+
+ protected Abdera abdera;
+  
+  protected AbstractAtompubWorkspaceProvider() {
+    addRequestProcessor(
+      TargetType.TYPE_SERVICE, 
+      ServiceRequestProcessor.class,
+      this);
+    addRequestProcessor(
+      TargetType.TYPE_CATEGORIES, 
+      CategoriesRequestProcessor.class, 
+      this);
+    addRequestProcessor(
+      TargetType.TYPE_COLLECTION,
+      CollectionRequestProcessor.class,
+      ProviderHelper.isAtom(),
+      this);
+    addRequestProcessor(
+      TargetType.TYPE_ENTRY, 
+      EntryRequestProcessor.class,
+      this);
+    addRequestProcessor(
+      TargetType.TYPE_MEDIA, 
+      MediaRequestProcessor.class,
+      this);
+  }
+  
+  public void init(Map<String, Object> properties) {
+    this.abdera = 
+      properties != null && 
+      properties.containsKey("abdera") ?
+        (Abdera)properties.get("abdera") :
+        Abdera.getInstance();
+    super.init(properties);
+  }
+
+  public Abdera getAbdera() {
+    return abdera;
+  }
+
+  public ResponseContext createErrorResponse(int code, String message, Throwable t) {
+    return AbstractAtompubProvider.createErrorResponse(abdera,code,message,t);
+  }
+  
+}
\ No newline at end of file

Propchange: abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubWorkspaceProvider.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractEntityCollectionAdapter.java
URL: http://svn.apache.org/viewvc/abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractEntityCollectionAdapter.java?rev=1239237&view=auto
==============================================================================
--- abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractEntityCollectionAdapter.java (added)
+++ abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractEntityCollectionAdapter.java Wed Feb  1 17:54:54 2012
@@ -0,0 +1,723 @@
+/*
+ * 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.protocol.server.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import javax.activation.MimeType;
+
+import org.apache.abdera2.Abdera;
+import org.apache.abdera2.factory.Factory;
+import org.apache.abdera2.common.iri.IRI;
+import org.apache.abdera2.common.text.UrlEncoding;
+import org.apache.abdera2.common.text.CharUtils.Profile;
+import org.apache.abdera2.common.date.DateTimes;
+import org.apache.abdera2.model.Content;
+import org.apache.abdera2.model.Entry;
+import org.apache.abdera2.model.Feed;
+import org.apache.abdera2.model.Person;
+import org.apache.abdera2.model.Text;
+import org.apache.abdera2.parser.ParseException;
+import org.apache.abdera2.util.MorePredicates;
+import org.apache.abdera2.common.http.EntityTag;
+import org.apache.abdera2.common.mediatype.MimeTypeHelper;
+import org.apache.abdera2.common.protocol.RequestContext;
+import org.apache.abdera2.common.protocol.ResponseContext;
+import org.apache.abdera2.common.protocol.EmptyResponseContext;
+import org.apache.abdera2.common.protocol.MediaResponseContext;
+import org.apache.abdera2.common.protocol.ProviderHelper;
+import org.apache.abdera2.common.protocol.ResponseContextException;
+import org.apache.abdera2.common.protocol.TargetType;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.joda.time.DateTime;
+
+import com.google.common.base.Function;
+
+/**
+ * By extending this class it becomes easy to build Collections which are backed by a set of entities - such as a
+ * database row, domain objects, or files.
+ * 
+ * @param <T> The entity that this is backed by.
+ */
+public abstract class AbstractEntityCollectionAdapter<T> 
+  extends AbstractAtompubCollectionAdapter {
+
+  private final static Log log = LogFactory.getLog(AbstractEntityCollectionAdapter.class);
+
+  public AbstractEntityCollectionAdapter(String href) {
+    super(href);
+    putHandler(TargetType.TYPE_COLLECTION,"POST",handlePost());
+    putHandler(TargetType.TYPE_COLLECTION,"GET",getItemList());
+    putHandler(TargetType.TYPE_COLLECTION,"HEAD",getItemList());
+    putHandler(TargetType.TYPE_MEDIA,"PUT",putMedia());
+    putHandler(TargetType.TYPE_MEDIA,"DELETE",deleteMedia());
+    putHandler(TargetType.TYPE_MEDIA, "HEAD", headMedia());
+    putHandler(TargetType.TYPE_MEDIA, "GET", getMedia());
+    putHandler(TargetType.TYPE_ENTRY,"DELETE",deleteItem());
+    putHandler(TargetType.TYPE_ENTRY,"GET",getItem());
+    putHandler(TargetType.TYPE_ENTRY,"HEAD",headItem());
+    putHandler(TargetType.TYPE_ENTRY,"PUT",putItem());
+  }
+  
+    /**
+     * Create a new entry
+     * 
+     * @param title The title of the entry (assumes that type="text")
+     * @param id The value of the atom:id element
+     * @param summary The summary of the entry
+     * @param updated The value of the atom:updated element
+     * @param authors Listing of atom:author elements
+     * @param context The content of the entry
+     * @param request The request context
+     */
+    public abstract T postEntry(String title,
+                                IRI id,
+                                String summary,
+                                DateTime updated,
+                                List<Person> authors,
+                                Content content,
+                                RequestContext request) throws ResponseContextException;
+
+    Function<RequestContext,ResponseContext> postMedia() {
+      return new Function<RequestContext,ResponseContext>() {
+        public ResponseContext apply(RequestContext input) {
+          return createMediaEntry(input);
+        }
+      };
+    }
+    
+    private Function<RequestContext,ResponseContext> putMedia() {
+      return new Function<RequestContext,ResponseContext>() {
+        public ResponseContext apply(RequestContext input) {
+          try {
+            String id = getResourceName(input);
+            T entryObj = getEntry(id, input);
+            putMedia(entryObj, input.getContentType(), input.getSlug(), input.getInputStream(), input);
+            return new EmptyResponseContext(200);
+          } catch (IOException e) {
+              return new EmptyResponseContext(500);
+          } catch (ResponseContextException e) {
+              return createErrorResponse(e);
+          }
+        }
+      };
+    }
+
+    /**
+     * Update a media resource. By default this method is not allowed. Implementations must override this method to
+     * support media resource updates
+     * 
+     * @param entryObj
+     * @param contentType The mime-type of the media resource
+     * @param slug The value of the Slug request header
+     * @param inputStream An input stream providing access to the request payload
+     * @param request The request context
+     */
+    public void putMedia(T entryObj, MimeType contentType, String slug, InputStream inputStream, RequestContext request)
+        throws ResponseContextException {
+        throw new ResponseContextException(ProviderHelper.notallowed(request));
+    }
+
+    Function<RequestContext,ResponseContext> postItem() {
+      return new Function<RequestContext,ResponseContext>() {
+        public ResponseContext apply(RequestContext input) {
+          return createNonMediaEntry(input);
+        }
+      };
+    }
+    
+    private Function<RequestContext,ResponseContext> handlePost() {
+      return new Function<RequestContext,ResponseContext>() {
+        public ResponseContext apply(RequestContext input) {
+          return AbstractAtompubProvider.IS_ATOM.apply(input) ?
+            postItem().apply(input) :
+            postMedia().apply(input);
+        }
+      };
+    }
+    
+    protected String getLink(T entryObj, IRI feedIri, RequestContext request) throws ResponseContextException {
+        return getLink(entryObj, feedIri, request, false);
+    }
+
+    protected String getLink(T entryObj, IRI feedIri, RequestContext request, boolean absolute)
+        throws ResponseContextException {
+        return getLink(getName(entryObj), entryObj, feedIri, request, absolute);
+    }
+
+    protected String getLink(String name, T entryObj, IRI feedIri, RequestContext request) {
+        return getLink(name, entryObj, feedIri, request, false);
+    }
+
+    protected String getLink(String name, T entryObj, IRI feedIri, RequestContext request, boolean absolute) {
+        feedIri = feedIri.trailingSlash();
+        IRI entryIri = feedIri.resolve(UrlEncoding.encode(name, Profile.PATH));
+
+        if (absolute) {
+            entryIri = request.getResolvedUri().resolve(entryIri);
+        }
+
+        String link = entryIri.toString();
+
+        String qp = getQueryParameters(entryObj, request);
+        if (qp != null && !"".equals(qp)) {
+            StringBuilder sb = new StringBuilder();
+            sb.append(link).append("?").append(qp);
+            link = sb.toString();
+        }
+
+        return link;
+    }
+
+    protected String getQueryParameters(T entryObj, RequestContext request) {
+        return null;
+    }
+
+    /**
+     * Post a new media resource to the collection. By default, this method is not supported. Implementations must
+     * override this method to support posting media resources
+     * 
+     * @param mimeType The mime-type of the resource
+     * @param slug The value of the Slug header
+     * @param inputStream An InputStream providing access to the request payload
+     * @param request The request context
+     */
+    public T postMedia(MimeType mimeType, String slug, InputStream inputStream, RequestContext request)
+        throws ResponseContextException {
+        throw new UnsupportedOperationException();
+    }
+    
+    private Function<RequestContext,ResponseContext> deleteItem() {
+      return new Function<RequestContext,ResponseContext>() {
+        public ResponseContext apply(RequestContext input) {
+          String id = getResourceName(input);
+          if (id != null) {
+              try {
+                  deleteEntry(id, input);
+              } catch (ResponseContextException e) {
+                  return createErrorResponse(e);
+              }
+              return new EmptyResponseContext(204);
+          } else {
+            return new EmptyResponseContext(404);
+          }
+        }
+      };
+    }
+
+    /**
+     * Delete an entry
+     * 
+     * @param resourceName The entry to delete
+     * @param request The request context
+     */
+    public abstract void deleteEntry(String resourceName, RequestContext request) throws ResponseContextException;
+
+    private Function<RequestContext,ResponseContext> deleteMedia() {
+      return new Function<RequestContext,ResponseContext>() {
+        public ResponseContext apply(RequestContext input) {
+          String resourceName = getResourceName(input);
+          if (resourceName != null) {
+              try {
+                  deleteMedia(resourceName, input);
+              } catch (ResponseContextException e) {
+                  return createErrorResponse(e);
+              }
+              return new EmptyResponseContext(204);
+          } else {
+              return new EmptyResponseContext(404);
+          }
+        }
+      };
+    }
+
+    /**
+     * Delete a media resource. By default this method is not supported. Implementations must override this method to
+     * support deleting media resources
+     */
+    public void deleteMedia(String resourceName, RequestContext request) throws ResponseContextException {
+        throw new ResponseContextException(ProviderHelper.notsupported(request));
+    }
+
+    /**
+     * Get the authors for an entry. By default this returns null. Implementations must override in order to providing a
+     * listing of authors for an entry
+     */
+    public List<Person> getAuthors(T entry, RequestContext request) throws ResponseContextException {
+        return null;
+    }
+
+    /**
+     * Get the content for the entry.
+     */
+    public abstract Object getContent(T entry, RequestContext request) throws ResponseContextException;
+
+    // GET, POST, PUT, DELETE
+
+    /**
+     * Get the content-type for the entry. By default this operation is not supported.
+     */
+    public String getContentType(T entry) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Get the listing of entries requested
+     */
+    public abstract Iterable<T> getEntries(RequestContext request) throws ResponseContextException;
+
+    private Function<RequestContext,ResponseContext> getItem() {
+      return new Function<RequestContext,ResponseContext>() {
+        public ResponseContext apply(RequestContext input) {
+          try {
+            Entry entry = getEntryFromCollectionProvider(input);
+            if (entry != null) {
+                return buildGetEntryResponse(input, entry);
+            } else {
+                return new EmptyResponseContext(404);
+            }
+        } catch (ResponseContextException e) {
+            return createErrorResponse(e);
+        }
+        }
+      };
+    }
+   
+    /**
+     * Get a specific entry
+     * 
+     * @param resourceName The entry to get
+     * @param request The request context
+     */
+    public abstract T getEntry(String resourceName, RequestContext request) throws ResponseContextException;
+
+    private Function<RequestContext,ResponseContext> headItem() {
+      return new Function<RequestContext,ResponseContext>() {
+        public ResponseContext apply(RequestContext input) {
+          try {
+            String resourceName = getResourceName(input);
+            T entryObj = getEntry(resourceName, input);
+            if (entryObj != null) {
+                return buildHeadEntryResponse(input, resourceName, getUpdated(entryObj));
+            } else {
+                return new EmptyResponseContext(404);
+            }
+        } catch (ResponseContextException e) {
+            return createErrorResponse(e);
+        }
+        }
+      };
+    }
+    
+    private Function<RequestContext,ResponseContext> headMedia() {
+      return new Function<RequestContext,ResponseContext>() {
+        public ResponseContext apply(RequestContext input) {
+          try {
+            String resourceName = getResourceName(input);
+            T entryObj = getEntry(resourceName, input);
+
+            if (entryObj != null) {
+                return buildHeadEntryResponse(input, resourceName, getUpdated(entryObj));
+            } else {
+                return new EmptyResponseContext(404);
+            }
+        } catch (ResponseContextException e) {
+            return createErrorResponse(e);
+        }
+        }
+      };
+    }
+
+    public Function<RequestContext,ResponseContext> getItemList() {
+      return new Function<RequestContext,ResponseContext>() {
+        public ResponseContext apply(RequestContext input) {
+          try {
+            Feed feed = createFeedBase(input);
+            addFeedDetails(feed, input);
+            return buildGetFeedResponse(feed);
+        } catch (ResponseContextException e) {
+            return createErrorResponse(e);
+        }
+        }
+      };
+    }
+
+
+    /**
+     * Adds the selected entries to the Feed document. By default, this will set the feed's atom:updated element to the
+     * current date and time
+     */
+    protected void addFeedDetails(Feed feed, RequestContext request) throws ResponseContextException {
+        feed.setUpdated(DateTime.now());
+
+        Iterable<T> entries = getEntries(request);
+        if (entries != null) {
+            for (T entryObj : entries) {
+                Entry e = feed.addEntry();
+
+                IRI feedIri = new IRI(getFeedIriForEntry(entryObj, request));
+                addEntryDetails(request, e, feedIri, entryObj);
+
+                if (isMediaEntry(entryObj)) {
+                    addMediaContent(feedIri, e, entryObj, request);
+                } else {
+                    addContent(e, entryObj, request);
+                }
+            }
+        }
+    }
+
+    private IRI getFeedIRI(T entryObj, RequestContext request) {
+        String feedIri = getFeedIriForEntry(entryObj, request);
+        return new IRI(feedIri).trailingSlash();
+    }
+
+    /**
+     * Gets the UUID for the specified entry.
+     * 
+     * @param entry
+     * @return
+     */
+    public abstract String getId(T entry) throws ResponseContextException;
+
+    private Function<RequestContext,ResponseContext> getMedia() {
+      return new Function<RequestContext,ResponseContext>() {
+        public ResponseContext apply(RequestContext input) {
+          try {
+            String resource = getResourceName(input);
+            T entryObj = getEntry(resource, input);
+            if (entryObj == null) {
+                return new EmptyResponseContext(404);
+            }
+            return buildGetMediaResponse(resource, entryObj);
+        } catch (ParseException pe) {
+            return new EmptyResponseContext(415);
+        } catch (ClassCastException cce) {
+            return new EmptyResponseContext(415);
+        } catch (ResponseContextException e) {
+            return e.getResponseContext();
+        } catch (Exception e) {
+            log.warn(e.getMessage(), e);
+            return new EmptyResponseContext(400);
+        }
+        }
+      };
+    }
+    
+    /**
+     * Creates a ResponseContext for a GET media request. By default, this returns a MediaResponseContext containing the
+     * media resource. The last-modified header will be set.
+     */
+    protected ResponseContext buildGetMediaResponse(String id, T entryObj) throws ResponseContextException {
+        DateTime updated = getUpdated(entryObj);
+        return new MediaResponseContext(getMediaStream(entryObj), updated, 200)
+          .setContentType(getContentType(entryObj))
+          .setEntityTag(EntityTag.generate(id, DateTimes.format(updated)));
+    }
+
+    /**
+     * Get the name of the media resource. By default this method is unsupported. Implementations must override.
+     */
+    public String getMediaName(T entry) throws ResponseContextException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Get an input stream for the media resource. By default this method is unsupported. Implementations must override.
+     */
+    public InputStream getMediaStream(T entry) throws ResponseContextException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Get the name of the entry resource (used to construct links)
+     */
+    public abstract String getName(T entry) throws ResponseContextException;
+
+    /**
+     * Get the title fo the entry
+     */
+    public abstract String getTitle(T entry) throws ResponseContextException;
+
+    /**
+     * Get the value to use in the atom:updated element
+     */
+    public abstract DateTime getUpdated(T entry) throws ResponseContextException;
+
+    /**
+     * True if this entry is a media-link entry. By default this always returns false. Implementations must override to
+     * support media link entries
+     */
+    public boolean isMediaEntry(T entry) throws ResponseContextException {
+        return false;
+    }
+
+    private Function<RequestContext,ResponseContext> putItem() {
+      return new Function<RequestContext,ResponseContext>() {
+        public ResponseContext apply(RequestContext input) {
+          try {
+            String id = getResourceName(input);
+            T entryObj = getEntry(id, input);
+
+            if (entryObj == null) {
+                return new EmptyResponseContext(404);
+            }
+
+            Entry orig_entry =
+                getEntryFromCollectionProvider(entryObj, new IRI(getFeedIriForEntry(entryObj, input)), input);
+            if (orig_entry != null) {
+
+                MimeType contentType = input.getContentType();
+                if (contentType != null && !MimeTypeHelper.isAtom(contentType.toString()))
+                    return new EmptyResponseContext(415);
+
+                Entry entry = getEntryFromRequest(input);
+                if (entry != null) {
+                    if (!entry.getId().equals(orig_entry.getId()))
+                        return new EmptyResponseContext(409);
+
+                    if (!MorePredicates.VALID_ENTRY.apply(entry))
+                        return new EmptyResponseContext(400);
+
+                    putEntry(entryObj, entry.getTitle(), DateTime.now(), entry.getAuthors(), entry.getSummary(), entry
+                        .getContentElement(), input);
+                    return new EmptyResponseContext(204);
+                } else {
+                    return new EmptyResponseContext(400);
+                }
+            } else {
+                return new EmptyResponseContext(404);
+            }
+        } catch (ResponseContextException e) {
+            return createErrorResponse(e);
+        } catch (ParseException pe) {
+            return new EmptyResponseContext(415);
+        } catch (ClassCastException cce) {
+            return new EmptyResponseContext(415);
+        } catch (Exception e) {
+            log.warn(e.getMessage(), e);
+            return new EmptyResponseContext(400);
+        }
+        }
+      };
+    }
+    
+    /**
+     * Get the Feed IRI
+     */
+    protected String getFeedIriForEntry(T entryObj, RequestContext request) {
+        return getHref(request);
+    }
+
+    /**
+     * Update an entry.
+     * 
+     * @param entry The entry to update
+     * @param title The new title of the entry
+     * @param updated The new value of atom:updated
+     * @param authors To new listing of authors
+     * @param summary The new summary
+     * @param content The new content
+     * @param request The request context
+     */
+    public abstract void putEntry(T entry,
+                                  String title,
+                                  DateTime updated,
+                                  List<Person> authors,
+                                  String summary,
+                                  Content content,
+                                  RequestContext request) throws ResponseContextException;
+
+    /**
+     * Adds the atom:content element to an entry
+     */
+    protected void addContent(Entry e, T doc, RequestContext request) throws ResponseContextException {
+        Object content = getContent(doc, request);
+
+        if (content instanceof Content) {
+            e.setContentElement((Content)content);
+        } else if (content instanceof String) {
+            e.setContent((String)content);
+        }
+    }
+
+    /**
+     * Add the details to an entry
+     * 
+     * @param request The request context
+     * @param e The entry
+     * @param feedIri The feed IRI
+     * @param entryObj
+     */
+    protected String addEntryDetails(RequestContext request, Entry e, IRI feedIri, T entryObj)
+        throws ResponseContextException {
+        String link = getLink(entryObj, feedIri, request);
+
+        e.addLink(link, "edit");
+        e.setId(getId(entryObj));
+        e.setTitle(getTitle(entryObj));
+        e.setUpdated(getUpdated(entryObj));
+
+        List<Person> authors = getAuthors(entryObj, request);
+        if (authors != null) {
+            for (Person a : authors) {
+                e.addAuthor(a);
+            }
+        }
+
+        Text t = getSummary(entryObj, request);
+        if (t != null) {
+            e.setSummaryElement(t);
+        }
+        return link;
+    }
+
+    /**
+     * Get the summary of the entry. By default this returns null.
+     */
+    public Text getSummary(T entry, RequestContext request) throws ResponseContextException {
+        return null;
+    }
+
+    /**
+     * Add media content details to a media-link entry
+     * 
+     * @param feedIri The feed iri
+     * @param entry The entry object
+     * @param entryObj
+     * @param request The request context
+     */
+    protected String addMediaContent(IRI feedIri, Entry entry, T entryObj, RequestContext request)
+        throws ResponseContextException {
+        String name = getMediaName(entryObj);
+
+        IRI mediaIri = new IRI(getLink(name, entryObj, feedIri, request));
+        String mediaLink = mediaIri.toString();
+        entry.setContent(mediaIri, getContentType(entryObj));
+        entry.addLink(mediaLink, "edit-media");
+
+        return mediaLink;
+    }
+
+    /**
+     * Create a media entry
+     * 
+     * @param request The request context
+     */
+    protected ResponseContext createMediaEntry(RequestContext request) {
+        try {
+            T entryObj = postMedia(request.getContentType(), request.getSlug(), request.getInputStream(), request);
+
+            IRI feedUri = getFeedIRI(entryObj, request);
+
+            Entry entry = AbstractAtompubProvider.getAbdera(request).getFactory().newEntry();
+            addEntryDetails(request, entry, feedUri, entryObj);
+            addMediaContent(feedUri, entry, entryObj, request);
+
+            String location = getLink(entryObj, feedUri, request, true);
+            return buildPostMediaEntryResponse(location, entry);
+        } catch (UnsupportedOperationException e) {
+          return UNSUPPORTED_TYPE.apply(request);
+        } catch (IOException e) {
+            return new EmptyResponseContext(500);
+        } catch (ResponseContextException e) {
+            return createErrorResponse(e);
+        }
+    }
+
+    /**
+     * Create a regular entry
+     * 
+     * @param request The request context
+     */
+    protected ResponseContext createNonMediaEntry(RequestContext request) {
+        try {
+            Entry entry = getEntryFromRequest(request);
+            if (entry != null) {
+                if (!MorePredicates.VALID_ENTRY.apply(entry))
+                    return new EmptyResponseContext(400);
+
+                entry.setUpdated(DateTime.now());
+
+                T entryObj =
+                    postEntry(entry.getTitle(), entry.getId(), entry.getSummary(), entry.getUpdated(), entry
+                        .getAuthors(), entry.getContentElement(), request);
+
+                entry.getIdElement().setValue(getId(entryObj));
+
+                IRI feedUri = getFeedIRI(entryObj, request);
+
+                String link = getLink(entryObj, feedUri, request);
+                entry.addLink(link, "edit");
+
+                String location = getLink(entryObj, feedUri, request, true);
+                return buildCreateEntryResponse(location, entry);
+            } else {
+                return new EmptyResponseContext(400);
+            }
+        } catch (ResponseContextException e) {
+            return createErrorResponse(e);
+        }
+    }
+
+    protected Entry getEntryFromCollectionProvider(RequestContext request) throws ResponseContextException {
+        String id = getResourceName(request);
+        T entryObj = getEntry(id, request);
+
+        if (entryObj == null) {
+            return null;
+        }
+
+        IRI feedIri = new IRI(getFeedIriForEntry(entryObj, request));
+        return getEntryFromCollectionProvider(entryObj, feedIri, request);
+    }
+
+    Entry getEntryFromCollectionProvider(T entryObj, IRI feedIri, RequestContext request)
+        throws ResponseContextException {
+        Abdera abdera = AbstractAtompubProvider.getAbdera(request);
+        Factory factory = abdera.getFactory();
+        Entry entry = factory.newEntry();
+
+        return buildEntry(entryObj, entry, feedIri, request);
+    }
+
+    /**
+     * Build the entry from the source object
+     * 
+     * @param entryObj The source object
+     * @param entry The entry to build
+     * @param feedIri The feed IRI
+     * @param request The request context
+     */
+    private Entry buildEntry(T entryObj, Entry entry, IRI feedIri, RequestContext request)
+        throws ResponseContextException {
+        addEntryDetails(request, entry, feedIri, entryObj);
+
+        if (isMediaEntry(entryObj)) {
+            addMediaContent(feedIri, entry, entryObj, request);
+        } else {
+            addContent(entry, entryObj, request);
+        }
+
+        return entry;
+    }
+
+}

Propchange: abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractEntityCollectionAdapter.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractEntityCollectionAdapter.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/DefaultAtompubProvider.java
URL: http://svn.apache.org/viewvc/abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/DefaultAtompubProvider.java?rev=1239237&view=auto
==============================================================================
--- abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/DefaultAtompubProvider.java (added)
+++ abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/DefaultAtompubProvider.java Wed Feb  1 17:54:54 2012
@@ -0,0 +1,126 @@
+/*
+ * 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.protocol.server.impl;
+
+import java.util.Collection;
+
+import javax.security.auth.Subject;
+
+import org.apache.abdera2.common.protocol.DefaultWorkspaceManager;
+import org.apache.abdera2.common.protocol.RequestContext;
+import org.apache.abdera2.common.protocol.Request;
+import org.apache.abdera2.common.protocol.RouteManager;
+import org.apache.abdera2.common.protocol.Target;
+import org.apache.abdera2.common.protocol.TargetBuilder;
+import org.apache.abdera2.common.protocol.TargetType;
+import org.apache.abdera2.common.protocol.WorkspaceInfo;
+import org.apache.abdera2.common.protocol.WorkspaceManager;
+
+import com.google.common.base.Function;
+
+/**
+ * The DefaultProvider is the default Provider implementation for Abdera. It supports multiple collections and assumes a
+ * simple http://.../{collection}/{entry} URL structure. Media-link entries are not supported.
+ */
+public class DefaultAtompubProvider 
+  extends AbstractAtompubProvider {
+
+    protected Function<RequestContext,Target> targetResolver;
+    protected Function<Request,Subject> subjectResolver;
+    protected TargetBuilder<?> targetBuilder;
+    protected RouteManager<TargetType,RequestContext,String> routeManager;
+
+    public DefaultAtompubProvider() {
+        this("/");
+    }
+
+    public DefaultAtompubProvider(String base) {
+      super(new DefaultWorkspaceManager());
+      if (base == null)
+        base = "/";
+      routeManager =
+        RouteManager.<TargetType,RequestContext,String>make()
+          .with("service", base, TargetType.TYPE_SERVICE)
+          .with("feed", base + ":collection", TargetType.TYPE_COLLECTION)
+          .with("entry", base + ":collection/:entry", TargetType.TYPE_ENTRY)
+          .with("categories", base + ":collection/:entry;categories", TargetType.TYPE_CATEGORIES)
+          .get();
+      targetBuilder = routeManager;
+      targetResolver = routeManager;
+    }
+
+    @SuppressWarnings("rawtypes")
+    public RouteManager getRouteManager() {
+        return routeManager;
+    }
+
+    protected Function<RequestContext,Target> getTargetResolver(RequestContext request) {
+        return targetResolver;
+    }
+
+    public void setTargetResolver(Function<RequestContext,Target> targetResolver) {
+        this.targetResolver = targetResolver;
+    }
+
+    protected Function<Request,Subject> getSubjectResolver(RequestContext request) {
+        return subjectResolver;
+    }
+
+    public void setSubjectResolver(Function<Request,Subject> subjectResolver) {
+        this.subjectResolver = subjectResolver;
+    }
+
+    public Function<RequestContext,Target> getTargetResolver() {
+        return targetResolver;
+    }
+
+    public Function<Request,Subject> getSubjectResolver() {
+        return subjectResolver;
+    }
+
+    public WorkspaceManager getWorkspaceManager() {
+        return workspaceManager;
+    }
+
+    public void setWorkspaceManager(WorkspaceManager workspaceManager) {
+        this.workspaceManager = workspaceManager;
+    }
+
+    @SuppressWarnings("rawtypes")
+    public TargetBuilder getTargetBuilder() {
+        return (TargetBuilder)targetBuilder;
+    }
+
+    public void setTargetBuilder(TargetBuilder<?> targetBuilder) {
+        this.targetBuilder = targetBuilder;
+    }
+
+    public void addWorkspace(WorkspaceInfo workspace) {
+        ((DefaultWorkspaceManager)getWorkspaceManager()).addWorkspace(workspace);
+    }
+
+    public void addWorkspaces(Collection<WorkspaceInfo> workspaces) {
+      for (WorkspaceInfo w : workspaces)
+        ((DefaultWorkspaceManager)getWorkspaceManager()).addWorkspace(w);
+    }
+
+    @SuppressWarnings("rawtypes")
+    protected TargetBuilder getTargetBuilder(Request request) {
+        return (TargetBuilder)targetBuilder;
+    }
+}

Propchange: abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/DefaultAtompubProvider.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleCategoriesInfo.java
URL: http://svn.apache.org/viewvc/abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleCategoriesInfo.java?rev=1239237&view=auto
==============================================================================
--- abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleCategoriesInfo.java (added)
+++ abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleCategoriesInfo.java Wed Feb  1 17:54:54 2012
@@ -0,0 +1,140 @@
+/*
+ * 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.protocol.server.impl;
+
+import java.io.Serializable;
+import java.util.Iterator;
+
+import org.apache.abdera2.common.misc.MoreFunctions;
+import org.apache.abdera2.common.protocol.RequestContext;
+import org.apache.abdera2.model.Categories;
+import org.apache.abdera2.protocol.server.model.AtompubCategoriesInfo;
+import org.apache.abdera2.protocol.server.model.AtompubCategoryInfo;
+
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableList;
+
+public class SimpleCategoriesInfo implements AtompubCategoriesInfo, Serializable {
+
+    public static Generator make() {
+      return new Generator();
+    }
+  
+    public static class Generator implements Supplier<AtompubCategoriesInfo> {
+      String href;
+      String scheme;
+      boolean fixed;
+      final ImmutableList.Builder<AtompubCategoryInfo> list = 
+        ImmutableList.builder();
+      public Generator href(String href) {
+        this.href = href;
+        return this;
+      }
+      public Generator scheme(String scheme) {
+        this.scheme = scheme;
+        return this;
+      }
+      public Generator fixed() {
+        this.fixed = true;
+        return this;
+      }
+      public Generator category(AtompubCategoryInfo info) {
+        this.list.add(info);
+        return this;
+      }
+      public AtompubCategoriesInfo get() {
+        return new SimpleCategoriesInfo(this);
+      }
+      
+    }
+  
+    private static final long serialVersionUID = 8732335394387909260L;
+
+    private final String href;
+    private final String scheme;
+    private final boolean fixed;
+    private final ImmutableList<AtompubCategoryInfo> list;
+
+    protected SimpleCategoriesInfo(Generator gen) {
+      this.href = gen.href;
+      this.scheme = gen.scheme;
+      this.fixed = gen.fixed;
+      this.list = gen.list.build();
+    }
+    
+    public String getHref(RequestContext request) {
+        return href;
+    }
+
+    public String getScheme(RequestContext request) {
+        return scheme;
+    }
+
+    public boolean isFixed(RequestContext request) {
+        return fixed;
+    }
+
+    public Iterator<AtompubCategoryInfo> iterator() {
+        return list.iterator();
+    }
+
+    public int hashCode() {
+      return MoreFunctions.genHashCode(1, fixed, href, list, scheme);
+    }
+
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        final SimpleCategoriesInfo other = (SimpleCategoriesInfo)obj;
+        if (fixed != other.fixed)
+            return false;
+        if (href == null) {
+            if (other.href != null)
+                return false;
+        } else if (!href.equals(other.href))
+            return false;
+        if (list == null) {
+            if (other.list != null)
+                return false;
+        } else if (!list.equals(other.list))
+            return false;
+        if (scheme == null) {
+            if (other.scheme != null)
+                return false;
+        } else if (!scheme.equals(other.scheme))
+            return false;
+        return true;
+    }
+
+    public Categories asCategoriesElement(RequestContext request) {
+        Categories cats = AbstractAtompubProvider.getAbdera(request).getFactory().newCategories();
+        if (href != null)
+            cats.setHref(href);
+        else {
+            cats.setFixed(fixed);
+            cats.setScheme(scheme);
+            for (AtompubCategoryInfo cat : this)
+                cats.addCategory(cat.asCategoryElement(request));
+        }
+        return cats;
+    }
+}

Propchange: abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleCategoriesInfo.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleCategoryInfo.java
URL: http://svn.apache.org/viewvc/abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleCategoryInfo.java?rev=1239237&view=auto
==============================================================================
--- abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleCategoryInfo.java (added)
+++ abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleCategoryInfo.java Wed Feb  1 17:54:54 2012
@@ -0,0 +1,120 @@
+/*
+ * 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.protocol.server.impl;
+
+import java.io.Serializable;
+
+import org.apache.abdera2.common.misc.MoreFunctions;
+import org.apache.abdera2.common.protocol.RequestContext;
+import org.apache.abdera2.model.Category;
+import org.apache.abdera2.protocol.server.model.AtompubCategoryInfo;
+
+import com.google.common.base.Supplier;
+
+public class SimpleCategoryInfo implements AtompubCategoryInfo, Serializable {
+
+    public static Generator make() {
+      return new Generator();
+    }
+  
+    public static class Generator implements Supplier<AtompubCategoryInfo> {
+      String label;
+      String term;
+      String scheme;
+      public Generator label(String label) {
+        this.label = label;
+        return this;
+      }
+      public Generator term(String term) {
+        this.term = term;
+        return this;
+      }
+      public Generator scheme(String scheme) {
+        this.scheme = scheme;
+        return this;
+      }
+      public AtompubCategoryInfo get() {
+        return new SimpleCategoryInfo(this);
+      }
+      
+    }
+  
+    private static final long serialVersionUID = -4013333222147077975L;
+    private final String label;
+    private final String term;
+    private final String scheme;
+
+    protected SimpleCategoryInfo(Generator gen) {
+      this.label = gen.label;
+      this.term = gen.term;
+      this.scheme = gen.scheme;
+    }
+    
+
+    public String getLabel(RequestContext request) {
+        return label;
+    }
+
+    public String getScheme(RequestContext request) {
+        return scheme;
+    }
+
+    public String getTerm(RequestContext request) {
+        return term;
+    }
+
+    public int hashCode() {
+      return MoreFunctions.genHashCode(1, label, scheme, term);
+    }
+
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        final SimpleCategoryInfo other = (SimpleCategoryInfo)obj;
+        if (label == null) {
+            if (other.label != null)
+                return false;
+        } else if (!label.equals(other.label))
+            return false;
+        if (scheme == null) {
+            if (other.scheme != null)
+                return false;
+        } else if (!scheme.equals(other.scheme))
+            return false;
+        if (term == null) {
+            if (other.term != null)
+                return false;
+        } else if (!term.equals(other.term))
+            return false;
+        return true;
+    }
+
+    public Category asCategoryElement(RequestContext request) {
+        Category cat = AbstractAtompubProvider.getAbdera(request).getFactory().newCategory();
+        cat.setTerm(term);
+        if (scheme != null)
+            cat.setScheme(scheme);
+        if (label != null)
+            cat.setLabel(label);
+        return cat;
+    }
+}

Propchange: abdera/abdera2-server/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleCategoryInfo.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Mime
View raw message