abdera-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jmsn...@apache.org
Subject svn commit: r1173209 [40/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/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubCollectionAdapter.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubCollectionAdapter.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubCollectionAdapter.java (added)
+++ abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubCollectionAdapter.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,156 @@
+/*
+ * 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.Date;
+import org.apache.abdera2.Abdera;
+import org.apache.abdera2.factory.Factory;
+import org.apache.abdera2.common.protocol.AbstractCollectionAdapter;
+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.AtompubCollectionAdapter;
+import org.apache.abdera2.protocol.server.AtompubMediaCollectionAdapter;
+import org.apache.abdera2.protocol.server.context.AtompubRequestContext;
+import org.apache.abdera2.protocol.server.context.FOMResponseContext;
+import org.apache.abdera2.protocol.server.model.AtompubCategoriesInfo;
+import org.apache.abdera2.protocol.server.model.AtompubCollectionInfo;
+
+/**
+ * Base CollectionAdapter implementation that provides a number of helper utility methods for adapter implementations.
+ */
+@SuppressWarnings("unchecked")
+public abstract class AbstractAtompubCollectionAdapter 
+  extends AbstractCollectionAdapter
+  implements AtompubCollectionAdapter, 
+             AtompubMediaCollectionAdapter,
+             AtompubCollectionInfo {
+
+      public String[] getAccepts(RequestContext request) {
+        return new String[] {"application/atom+xml;type=entry"};
+      }
+    
+    public AtompubCategoriesInfo[] getCategoriesInfo(RequestContext request) {
+        return null;
+    }
+    
+    public <S extends ResponseContext>S getCategories(RequestContext request) {
+        return null;
+    }
+  
+    /**
+     * 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 <S extends ResponseContext>S buildCreateEntryResponse(String link, Entry entry) {
+        FOMResponseContext<Entry> rc = new FOMResponseContext<Entry>(entry);
+        rc.setLocation(link);
+        rc.setContentLocation(rc.getLocation().toString());
+        rc.setEntityTag(AbstractAtompubProvider.calculateEntityTag(entry));
+        rc.setStatus(201);
+        return (S)rc;
+    }
+
+    /**
+     * 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 <S extends ResponseContext>S 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 <S extends ResponseContext>S buildGetEntryResponse(RequestContext request, Entry entry)
+        throws ResponseContextException {
+        Feed feed = createFeedBase(request);
+        entry.setSource(feed.getAsSource());
+        Document<Entry> entry_doc = entry.getDocument();
+        FOMResponseContext<Document<Entry>> rc = new FOMResponseContext<Document<Entry>>(entry_doc);
+        rc.setEntityTag(AbstractAtompubProvider.calculateEntityTag(entry));
+        return (S)rc;
+    }
+
+    /**
+     * Creates the ResponseContext for a GET feed request. By default, a BaseResponseContext is returned. The Etag
+     * header will be set.
+     */
+    protected <S extends ResponseContext>S buildGetFeedResponse(Feed feed) {
+        Document<Feed> document = feed.getDocument();
+        FOMResponseContext<Document<Feed>> rc = new FOMResponseContext<Document<Feed>>(document);
+        rc.setEntityTag(AbstractAtompubProvider.calculateEntityTag(document.getRoot()));
+        return (S)rc;
+    }
+
+    /**
+     * 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.setUpdated(new Date());
+        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 {
+            AtompubRequestContext context = (AtompubRequestContext) request;
+            entry_doc = (Document<Entry>)context.getDocument(parser).clone();
+        } catch (ParseException e) {
+            throw new ResponseContextException(400, e);
+        } catch (IOException e) {
+            throw new ResponseContextException(500, e);
+        }
+        if (entry_doc == null) {
+            return null;
+        }
+        return 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;
+    }
+}

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

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

Added: abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubProvider.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubProvider.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubProvider.java (added)
+++ abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubProvider.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,291 @@
+/*
+ * 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.Date;
+import java.util.List;
+import java.util.Map;
+import javax.xml.namespace.QName;
+
+import org.apache.abdera2.Abdera;
+import org.apache.abdera2.common.Constants;
+import org.apache.abdera2.common.Localizer;
+import org.apache.abdera2.common.date.DateTime;
+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.iri.IRI;
+import org.apache.abdera2.common.mediatype.MimeTypeHelper;
+import org.apache.abdera2.common.protocol.AbstractResponseContext;
+import org.apache.abdera2.common.protocol.BaseProvider;
+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.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.model.Base;
+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.ExtensibleElement;
+import org.apache.abdera2.model.Feed;
+import org.apache.abdera2.model.Link;
+import org.apache.abdera2.model.Service;
+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.AtompubRequestContext;
+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;
+
+/**
+ * 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 BaseProvider
+  implements AtompubProvider {
+
+    private final static Log log = LogFactory.getLog(AbstractAtompubProvider.class);
+    protected Abdera abdera;
+
+    protected AbstractAtompubProvider() {
+        this.requestProcessors.put(TargetType.TYPE_SERVICE, new ServiceRequestProcessor());
+        this.requestProcessors.put(TargetType.TYPE_CATEGORIES, new CategoriesRequestProcessor());
+        this.requestProcessors.put(TargetType.TYPE_COLLECTION, new CollectionRequestProcessor() {
+          protected boolean isAcceptableItemType(RequestContext context) {
+            return ProviderHelper.isAtom(context);
+          }
+        });
+        this.requestProcessors.put(TargetType.TYPE_ENTRY, new EntryRequestProcessor());
+        this.requestProcessors.put(TargetType.TYPE_MEDIA, new MediaRequestProcessor());
+    }
+
+    public void init(Abdera abdera, Map<String, String> properties) {
+        this.abdera = abdera == null ? abdera : Abdera.getInstance();
+        this.init(properties);
+    }
+
+    public Abdera getAbdera() {
+        return abdera;
+    }
+
+    protected Service getServiceElement(RequestContext request) {
+        Service service = abdera.newService();
+        for (WorkspaceInfo wi : getWorkspaceManager(request).getWorkspaces(request)) {
+            if (wi instanceof AtompubWorkspaceInfo) {
+              AtompubWorkspaceInfo awi = (AtompubWorkspaceInfo) wi;
+              service.addWorkspace(awi.asWorkspaceElement(request));
+            }
+        }
+        return service;
+    }
+    
+    @SuppressWarnings("unchecked")
+    public <S extends ResponseContext>S createErrorResponse(int code, String message, Throwable t) {
+      return (S)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) {
+        AbstractResponseContext rc = new StreamWriterResponseContext(abdera) {
+          @Override
+          protected void writeTo(StreamWriter sw) throws IOException {
+              Error.create(sw, code, message, t);
+          }
+        };
+        rc.setStatus(code);
+        rc.setStatusText(message);
+        return rc;
+      }
+
+    /**
+     * Check to see if the entry is minimally valid according to RFC4287. This is not a complete check. It just verifies
+     * that the appropriate elements are present and that their values can be accessed.
+     */
+    public static boolean isValidEntry(Entry entry) {
+        try {
+            IRI id = entry.getId();
+            if (id == null || id.toString().trim().length() == 0 || !id.isAbsolute())
+                return false;
+            if (entry.getTitle() == null)
+                return false;
+            if (entry.getUpdated() == null)
+                return false;
+            if (entry.getAuthor() == null && (entry.getSource() != null && entry.getSource().getAuthor() == null))
+                return false;
+            Content content = entry.getContentElement();
+            if (content == null) {
+                if (entry.getAlternateLink() == null)
+                    return false;
+            } else {
+                if ((content.getSrc() != null || content.getContentType() == Content.Type.MEDIA) && entry
+                    .getSummaryElement() == null) {
+                    ProviderHelper.log.debug(Localizer.sprintf("CHECKING.VALID.ENTRY", false));
+                    return false;
+                }
+            }
+        } catch (Exception e) {
+            ProviderHelper.log.debug(Localizer.sprintf("CHECKING.VALID.ENTRY", false));
+            return false;
+        }
+        ProviderHelper.log.debug(Localizer.sprintf("CHECKING.VALID.ENTRY", true));
+        return true;
+    }
+
+    /**
+     * Return false if the element contains any extension elements that are not supported
+     */
+    public static boolean checkElementNamespaces(Element element, List<String> ignore) {
+        List<QName> attrs = element.getExtensionAttributes();
+        for (QName qname : attrs) {
+            String ns = qname.getNamespaceURI();
+            if (!ignore.contains(ns))
+                return false;
+        }
+        if (element instanceof ExtensibleElement) {
+            ExtensibleElement ext = (ExtensibleElement)element;
+            for (Element el : ext.getExtensions()) {
+                QName qname = el.getQName();
+                String ns = qname.getNamespaceURI();
+                if (!ignore.contains(ns))
+                    return false;
+                if (!checkElementNamespaces(el, ignore))
+                    return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * 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 = DateTime.format(entry.getEdited() != null ? entry.getEdited() : entry.getUpdated());
+        } else if (base instanceof Feed) {
+            Feed feed = (Feed)base;
+            id = feed.getId().toString();
+            modified = DateTime.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, Date 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;
+    }
+
+    @Override
+    public <S extends ResponseContext> S process(RequestContext request) {
+      return super.process(request instanceof AtompubRequestContext?request:new AtompubRequestContext(request));
+    }
+}

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

Added: abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubWorkspaceProvider.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubWorkspaceProvider.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubWorkspaceProvider.java (added)
+++ abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractAtompubWorkspaceProvider.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+package org.apache.abdera2.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.RequestContext;
+import org.apache.abdera2.common.protocol.ResponseContext;
+import org.apache.abdera2.common.protocol.TargetType;
+import org.apache.abdera2.protocol.server.AtompubProvider;
+import org.apache.abdera2.protocol.server.context.AtompubRequestContext;
+import org.apache.abdera2.protocol.server.model.AtompubWorkspaceManager;
+import org.apache.abdera2.protocol.server.processors.CategoriesRequestProcessor;
+import org.apache.abdera2.protocol.server.processors.ServiceRequestProcessor;
+
+public abstract class AbstractAtompubWorkspaceProvider 
+  extends AbstractWorkspaceProvider
+  implements AtompubProvider, 
+             AtompubWorkspaceManager {
+
+ protected Abdera abdera;
+  
+  protected AbstractAtompubWorkspaceProvider() {
+    this.requestProcessors.put(TargetType.TYPE_SERVICE, new ServiceRequestProcessor());
+    this.requestProcessors.put(TargetType.TYPE_CATEGORIES, new CategoriesRequestProcessor());
+    this.requestProcessors.put(TargetType.TYPE_COLLECTION, new CollectionRequestProcessor() {
+      protected boolean isAcceptableItemType(RequestContext context) {
+        return ProviderHelper.isAtom(context);
+      }
+    });
+    this.requestProcessors.put(TargetType.TYPE_ENTRY, new EntryRequestProcessor());
+    this.requestProcessors.put(TargetType.TYPE_MEDIA, new MediaRequestProcessor());
+  }
+  
+  public void init(Abdera abdera, Map<String, String> properties) {
+    super.init(properties);
+    this.abdera = abdera;
+  }
+
+  public Abdera getAbdera() {
+    return abdera;
+  }
+
+  @SuppressWarnings("unchecked")
+  public <S extends ResponseContext>S createErrorResponse(int code, String message, Throwable t) {
+    return (S)AbstractAtompubProvider.createErrorResponse(abdera,code,message,t);
+  }
+  
+  @Override
+  public <S extends ResponseContext> S process(RequestContext request) {
+    return super.process(request instanceof AtompubRequestContext?request:new AtompubRequestContext(request));
+  }
+}
\ No newline at end of file

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

Added: abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractEntityCollectionAdapter.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractEntityCollectionAdapter.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractEntityCollectionAdapter.java (added)
+++ abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractEntityCollectionAdapter.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,663 @@
+/*
+ * 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.Date;
+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.DateTime;
+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.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.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * 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.
+ */
+@SuppressWarnings("unchecked")
+public abstract class AbstractEntityCollectionAdapter<T> 
+  extends AbstractAtompubCollectionAdapter {
+
+  private final static Log log = LogFactory.getLog(AbstractEntityCollectionAdapter.class);
+
+    /**
+     * 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,
+                                Date updated,
+                                List<Person> authors,
+                                Content content,
+                                RequestContext request) throws ResponseContextException;
+
+    @Override
+    public <S extends ResponseContext>S postMedia(RequestContext request) {
+        return createMediaEntry(request);
+    }
+
+    @Override
+    public <S extends ResponseContext>S putMedia(RequestContext request) {
+        try {
+            String id = getResourceName(request);
+            T entryObj = getEntry(id, request);
+
+            putMedia(entryObj, request.getContentType(), request.getSlug(), request.getInputStream(), request);
+
+            return (S)new EmptyResponseContext(200);
+        } catch (IOException e) {
+            return (S)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));
+    }
+
+    public <S extends ResponseContext>S postItem(RequestContext request) {
+        return createNonMediaEntry(request);
+    }
+
+    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();
+    }
+
+    public <S extends ResponseContext>S deleteItem(RequestContext request) {
+        String id = getResourceName(request);
+        if (id != null) {
+
+            try {
+                deleteEntry(id, request);
+            } catch (ResponseContextException e) {
+                return createErrorResponse(e);
+            }
+
+            return (S)new EmptyResponseContext(204);
+        } else {
+            return (S)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;
+
+    public <S extends ResponseContext>S deleteMedia(RequestContext request) {
+        String resourceName = getResourceName(request);
+        if (resourceName != null) {
+
+            try {
+                deleteMedia(resourceName, request);
+            } catch (ResponseContextException e) {
+                return createErrorResponse(e);
+            }
+
+            return (S)new EmptyResponseContext(204);
+        } else {
+            return (S)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;
+
+    public <S extends ResponseContext>S getItem(RequestContext request) {
+        try {
+            Entry entry = getEntryFromCollectionProvider(request);
+            if (entry != null) {
+                return buildGetEntryResponse(request, entry);
+            } else {
+                return (S)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;
+
+    public <S extends ResponseContext>S headItem(RequestContext request) {
+        try {
+            String resourceName = getResourceName(request);
+            T entryObj = getEntry(resourceName, request);
+
+            if (entryObj != null) {
+                return buildHeadEntryResponse(request, resourceName, getUpdated(entryObj));
+            } else {
+                return (S)new EmptyResponseContext(404);
+            }
+        } catch (ResponseContextException e) {
+            return createErrorResponse(e);
+        }
+    }
+
+    public <S extends ResponseContext>S headMedia(RequestContext request) {
+        try {
+            String resourceName = getResourceName(request);
+            T entryObj = getEntry(resourceName, request);
+
+            if (entryObj != null) {
+                return buildHeadEntryResponse(request, resourceName, getUpdated(entryObj));
+            } else {
+                return (S)new EmptyResponseContext(404);
+            }
+        } catch (ResponseContextException e) {
+            return createErrorResponse(e);
+        }
+    }
+
+    public <S extends ResponseContext>S getItemList(RequestContext request) {
+        try {
+            Feed feed = createFeedBase(request);
+
+            addFeedDetails(feed, request);
+
+            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(new Date());
+
+        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;
+
+    public <S extends ResponseContext>S getMedia(RequestContext request) {
+        try {
+            String resource = getResourceName(request);
+            T entryObj = getEntry(resource, request);
+
+            if (entryObj == null) {
+                return (S)new EmptyResponseContext(404);
+            }
+
+            return buildGetMediaResponse(resource, entryObj);
+        } catch (ParseException pe) {
+            return (S)new EmptyResponseContext(415);
+        } catch (ClassCastException cce) {
+            return (S)new EmptyResponseContext(415);
+        } catch (ResponseContextException e) {
+            return e.getResponseContext();
+        } catch (Exception e) {
+            log.warn(e.getMessage(), e);
+            return (S)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 <S extends ResponseContext>S buildGetMediaResponse(String id, T entryObj) throws ResponseContextException {
+        Date updated = getUpdated(entryObj);
+        MediaResponseContext ctx = new MediaResponseContext(getMediaStream(entryObj), updated, 200);
+        ctx.setContentType(getContentType(entryObj));
+        ctx.setEntityTag(EntityTag.generate(id, DateTime.format(updated)));
+        return (S)ctx;
+    }
+
+    /**
+     * 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 Date 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;
+    }
+
+    public <S extends ResponseContext>S putItem(RequestContext request) {
+        try {
+            String id = getResourceName(request);
+            T entryObj = getEntry(id, request);
+
+            if (entryObj == null) {
+                return (S)new EmptyResponseContext(404);
+            }
+
+            Entry orig_entry =
+                getEntryFromCollectionProvider(entryObj, new IRI(getFeedIriForEntry(entryObj, request)), request);
+            if (orig_entry != null) {
+
+                MimeType contentType = request.getContentType();
+                if (contentType != null && !MimeTypeHelper.isAtom(contentType.toString()))
+                    return (S)new EmptyResponseContext(415);
+
+                Entry entry = getEntryFromRequest(request);
+                if (entry != null) {
+                    if (!entry.getId().equals(orig_entry.getId()))
+                        return (S)new EmptyResponseContext(409);
+
+                    if (!AbstractAtompubProvider.isValidEntry(entry))
+                        return (S)new EmptyResponseContext(400);
+
+                    putEntry(entryObj, entry.getTitle(), new Date(), entry.getAuthors(), entry.getSummary(), entry
+                        .getContentElement(), request);
+                    return (S)new EmptyResponseContext(204);
+                } else {
+                    return (S)new EmptyResponseContext(400);
+                }
+            } else {
+                return (S)new EmptyResponseContext(404);
+            }
+        } catch (ResponseContextException e) {
+            return createErrorResponse(e);
+        } catch (ParseException pe) {
+            return (S)new EmptyResponseContext(415);
+        } catch (ClassCastException cce) {
+            return (S)new EmptyResponseContext(415);
+        } catch (Exception e) {
+            log.warn(e.getMessage(), e);
+            return (S)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,
+                                  Date 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 <S extends ResponseContext>S 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 (IOException e) {
+            return (S)new EmptyResponseContext(500);
+        } catch (ResponseContextException e) {
+            return createErrorResponse(e);
+        }
+    }
+
+    /**
+     * Create a regular entry
+     * 
+     * @param request The request context
+     */
+    protected <S extends ResponseContext>S createNonMediaEntry(RequestContext request) {
+        try {
+            Entry entry = getEntryFromRequest(request);
+            if (entry != null) {
+                if (!AbstractAtompubProvider.isValidEntry(entry))
+                    return (S)new EmptyResponseContext(400);
+
+                entry.setUpdated(new Date());
+
+                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 (S)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/src/main/java/org/apache/abdera2/protocol/server/impl/AbstractEntityCollectionAdapter.java
------------------------------------------------------------------------------
    svn:executable = *

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

Added: abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/DefaultAtompubProvider.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/DefaultAtompubProvider.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/DefaultAtompubProvider.java (added)
+++ abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/DefaultAtompubProvider.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,133 @@
+/*
+ * 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.misc.Resolver;
+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;
+
+/**
+ * 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 WorkspaceManager workspaceManager;
+    protected Resolver<Target,RequestContext> targetResolver;
+    protected Resolver<Subject,Request> subjectResolver;
+    protected TargetBuilder<?> targetBuilder;
+    protected RouteManager<TargetType,RequestContext> routeManager;
+
+    public DefaultAtompubProvider() {
+        this("/");
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public DefaultAtompubProvider(String base) {
+        if (base == null) {
+            base = "/";
+        }
+        workspaceManager = new DefaultWorkspaceManager();
+        routeManager =
+            new RouteManager()
+              .addRoute("service", base, TargetType.TYPE_SERVICE)
+              .addRoute("feed", base + ":collection", TargetType.TYPE_COLLECTION)
+              .addRoute("entry", base + ":collection/:entry", TargetType.TYPE_ENTRY)
+              .addRoute("categories", base + ":collection/:entry;categories", TargetType.TYPE_CATEGORIES);
+
+        targetBuilder = routeManager;
+        targetResolver = routeManager;
+    }
+
+    @SuppressWarnings("rawtypes")
+    public RouteManager getRouteManager() {
+        return routeManager;
+    }
+
+    protected Resolver<Target,RequestContext> getTargetResolver(RequestContext request) {
+        return targetResolver;
+    }
+
+    public void setTargetResolver(Resolver<Target,RequestContext> targetResolver) {
+        this.targetResolver = targetResolver;
+    }
+
+    protected Resolver<Subject,Request> getSubjectResolver(RequestContext request) {
+        return subjectResolver;
+    }
+
+    public void setSubjectResolver(Resolver<Subject,Request> subjectResolver) {
+        this.subjectResolver = subjectResolver;
+    }
+
+    public Resolver<Target,RequestContext> getTargetResolver() {
+        return targetResolver;
+    }
+
+    public Resolver<Subject,Request> getSubjectResolver() {
+        return subjectResolver;
+    }
+
+    protected WorkspaceManager getWorkspaceManager(RequestContext request) {
+        return getWorkspaceManager();
+    }
+
+    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/src/main/java/org/apache/abdera2/protocol/server/impl/DefaultAtompubProvider.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleCategoriesInfo.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleCategoriesInfo.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleCategoriesInfo.java (added)
+++ abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleCategoriesInfo.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,137 @@
+/*
+ * 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.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+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;
+
+public class SimpleCategoriesInfo implements AtompubCategoriesInfo, Serializable {
+
+    private static final long serialVersionUID = 8732335394387909260L;
+
+    private final String href;
+    private final String scheme;
+    private final boolean fixed;
+    private final List<AtompubCategoryInfo> list = new ArrayList<AtompubCategoryInfo>();
+
+    public SimpleCategoriesInfo() {
+        this(null, false);
+    }
+
+    public SimpleCategoriesInfo(boolean fixed) {
+        this(null, fixed);
+    }
+
+    public SimpleCategoriesInfo(String href) {
+        this.href = href;
+        this.scheme = null;
+        this.fixed = false;
+    }
+
+    public SimpleCategoriesInfo(String scheme, boolean fixed, AtompubCategoryInfo... categories) {
+        this.href = null;
+        this.scheme = scheme;
+        this.fixed = fixed;
+        addCategoryInfo(categories);
+    }
+
+    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 SimpleCategoriesInfo addCategoryInfo(AtompubCategoryInfo... categories) {
+        for (AtompubCategoryInfo cat : categories)
+            list.add(cat);
+        return this;
+    }
+
+    public SimpleCategoriesInfo setCategoryInfo(AtompubCategoryInfo... categories) {
+        list.clear();
+        return addCategoryInfo(categories);
+    }
+
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (fixed ? 1231 : 1237);
+        result = prime * result + ((href == null) ? 0 : href.hashCode());
+        result = prime * result + ((list == null) ? 0 : list.hashCode());
+        result = prime * result + ((scheme == null) ? 0 : scheme.hashCode());
+        return result;
+    }
+
+    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/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleCategoriesInfo.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleCategoryInfo.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleCategoryInfo.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleCategoryInfo.java (added)
+++ abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleCategoryInfo.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,103 @@
+/*
+ * 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.protocol.RequestContext;
+import org.apache.abdera2.model.Category;
+import org.apache.abdera2.protocol.server.model.AtompubCategoryInfo;
+
+public class SimpleCategoryInfo implements AtompubCategoryInfo, Serializable {
+
+    private static final long serialVersionUID = -4013333222147077975L;
+    private final String label;
+    private final String term;
+    private final String scheme;
+
+    public SimpleCategoryInfo(String term) {
+        this(term, null, null);
+    }
+
+    public SimpleCategoryInfo(String term, String scheme) {
+        this(term, scheme, null);
+    }
+
+    public SimpleCategoryInfo(String term, String scheme, String label) {
+        this.term = term;
+        this.scheme = scheme;
+        this.label = label;
+    }
+
+    public String getLabel(RequestContext request) {
+        return label;
+    }
+
+    public String getScheme(RequestContext request) {
+        return scheme;
+    }
+
+    public String getTerm(RequestContext request) {
+        return term;
+    }
+
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((label == null) ? 0 : label.hashCode());
+        result = prime * result + ((scheme == null) ? 0 : scheme.hashCode());
+        result = prime * result + ((term == null) ? 0 : term.hashCode());
+        return result;
+    }
+
+    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/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleCategoryInfo.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleCollectionInfo.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleCollectionInfo.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleCollectionInfo.java (added)
+++ abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleCollectionInfo.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,94 @@
+/*
+ * 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.ArrayList;
+import java.util.List;
+
+import org.apache.abdera2.common.protocol.RequestContext;
+import org.apache.abdera2.common.protocol.BasicCollectionInfo;
+import org.apache.abdera2.model.Collection;
+import org.apache.abdera2.protocol.server.model.AtompubCategoriesInfo;
+import org.apache.abdera2.protocol.server.model.AtompubCollectionInfo;
+
+public class SimpleCollectionInfo 
+  extends BasicCollectionInfo
+  implements AtompubCollectionInfo, 
+             Serializable {
+
+    private static final long serialVersionUID = 8026455829158149510L;
+
+    private final List<AtompubCategoriesInfo> catinfos = 
+      new ArrayList<AtompubCategoriesInfo>();
+
+    public SimpleCollectionInfo(String title, String href, String... accepts) {
+        super(title,href,accepts);
+    }
+
+    public AtompubCategoriesInfo[] getCategoriesInfo(RequestContext request) {
+        return catinfos.toArray(new AtompubCategoriesInfo[catinfos.size()]);
+    }
+
+    public void addCategoriesInfo(AtompubCategoriesInfo... catinfos) {
+        for (AtompubCategoriesInfo catinfo : catinfos)
+            this.catinfos.add(catinfo);
+    }
+
+    public void setCategoriesInfo(AtompubCategoriesInfo... catinfos) {
+        this.catinfos.clear();
+        addCategoriesInfo(catinfos);
+    }
+
+    @Override
+    public int hashCode() {
+      final int prime = 31;
+      int result = super.hashCode();
+      result = prime * result + ((catinfos == null) ? 0 : catinfos.hashCode());
+      return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+      if (this == obj)
+        return true;
+      if (!super.equals(obj))
+        return false;
+      if (getClass() != obj.getClass())
+        return false;
+      SimpleCollectionInfo other = (SimpleCollectionInfo) obj;
+      if (catinfos == null) {
+        if (other.catinfos != null)
+          return false;
+      } else if (!catinfos.equals(other.catinfos))
+        return false;
+      return true;
+    }
+
+    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 : this.catinfos) {
+            collection.addCategories(catsinfo.asCategoriesElement(request));
+        }
+        return collection;
+    }
+
+}

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

Added: abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleWorkspaceInfo.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleWorkspaceInfo.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleWorkspaceInfo.java (added)
+++ abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/impl/SimpleWorkspaceInfo.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,52 @@
+/*
+ * 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.protocol.RequestContext;
+import org.apache.abdera2.common.protocol.BasicWorkspaceInfo;
+import org.apache.abdera2.common.protocol.CollectionInfo;
+import org.apache.abdera2.model.Workspace;
+import org.apache.abdera2.protocol.server.model.AtompubCollectionInfo;
+import org.apache.abdera2.protocol.server.model.AtompubWorkspaceInfo;
+
+public class SimpleWorkspaceInfo 
+  extends BasicWorkspaceInfo
+  implements AtompubWorkspaceInfo, Serializable {
+
+    private static final long serialVersionUID = -8459688584319762878L;
+
+    public SimpleWorkspaceInfo() {
+    }
+
+    public SimpleWorkspaceInfo(String title) {
+        super(title);
+    }
+
+    public Workspace asWorkspaceElement(RequestContext request) {
+        Workspace workspace = AbstractAtompubProvider.getAbdera(request).getFactory().newWorkspace();
+        workspace.setTitle(title);
+        for (CollectionInfo c : this.collections) {
+            AtompubCollectionInfo collection = (AtompubCollectionInfo) c;
+            workspace.addCollection(collection.asCollectionElement(request));
+        }
+        return workspace;
+    }
+
+}

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

Added: abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/model/AtompubCategoriesInfo.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/model/AtompubCategoriesInfo.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/model/AtompubCategoriesInfo.java (added)
+++ abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/model/AtompubCategoriesInfo.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,48 @@
+/*
+ * 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.model;
+
+import org.apache.abdera2.common.protocol.RequestContext;
+import org.apache.abdera2.model.Categories;
+
+/**
+ * Metadata interface used by WorkspaceManager and Provider implementations to construct Atompub Service Documents. The
+ * CategoriesInfo interface provides information used to construct an app:categories element within an app:collection.
+ */
+public interface AtompubCategoriesInfo extends Iterable<AtompubCategoryInfo> {
+
+    /**
+     * Return true of the app:categories element fixed attribute should be set
+     */
+    boolean isFixed(RequestContext request);
+
+    /**
+     * Return the value of the app:categories element scheme attribute or null if the scheme should be omitted
+     */
+    String getScheme(RequestContext request);
+
+    /**
+     * Return the value of the app:categories element href attribute or null if the href should be omitted
+     */
+    String getHref(RequestContext request);
+
+    /**
+     * Convert this into an instance of the FOM Categories interface
+     */
+    Categories asCategoriesElement(RequestContext request);
+}

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

Added: abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/model/AtompubCategoryInfo.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/model/AtompubCategoryInfo.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/model/AtompubCategoryInfo.java (added)
+++ abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/model/AtompubCategoryInfo.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+package org.apache.abdera2.protocol.server.model;
+
+import org.apache.abdera2.common.protocol.RequestContext;
+import org.apache.abdera2.model.Category;
+
+/**
+ * Metadata interface used by WorkspaceManager and Provider implementations to construct Atompub Service Documents. The
+ * CategoryInfo interface provides information used to construct an atom:category element within an app:categories
+ */
+public interface AtompubCategoryInfo {
+
+    /**
+     * Return the value of the atom:category scheme attribute or null if the scheme should be omitted
+     */
+    String getScheme(RequestContext request);
+
+    /**
+     * Return the value of the atom:category term attribute. This value MUST be provided
+     */
+    String getTerm(RequestContext request);
+
+    /**
+     * Return the value of the atom:category label attribute or null if the label should be omitted. This value is
+     * language-sensitive
+     */
+    String getLabel(RequestContext request);
+
+    /**
+     * Convert this into an instance of the FOM Category interface
+     */
+    Category asCategoryElement(RequestContext request);
+}

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

Added: abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/model/AtompubCollectionInfo.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/model/AtompubCollectionInfo.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/model/AtompubCollectionInfo.java (added)
+++ abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/model/AtompubCollectionInfo.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+package org.apache.abdera2.protocol.server.model;
+
+import org.apache.abdera2.common.protocol.RequestContext;
+import org.apache.abdera2.common.protocol.CollectionInfo;
+import org.apache.abdera2.model.Collection;
+
+/**
+ * Metadata interface used by WorkspaceManager and Provider implementations to construct Atompub Service Documents. The
+ * CollectionInfo interface provides information used to construct an app:collection element
+ */
+public interface AtompubCollectionInfo
+  extends CollectionInfo {
+
+    /**
+     * Return the collection of CategoriesInfo objects for the app:collection element's app:categories elements. These
+     * tell a client which atom:category elements are defined for use in the collections atom:entries
+     */
+    AtompubCategoriesInfo[] getCategoriesInfo(RequestContext request);
+
+    /**
+     * Converts this to an instance of the FOM Collection interface
+     */
+    Collection asCollectionElement(RequestContext request);
+
+}

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

Added: abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/model/AtompubWorkspaceInfo.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/model/AtompubWorkspaceInfo.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/model/AtompubWorkspaceInfo.java (added)
+++ abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/model/AtompubWorkspaceInfo.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,36 @@
+/*
+ * 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.model;
+
+
+import org.apache.abdera2.common.protocol.RequestContext;
+import org.apache.abdera2.common.protocol.WorkspaceInfo;
+import org.apache.abdera2.model.Workspace;
+
+/**
+ * Metadata interface used by WorkspaceManager and Provider implementations to construct Atompub Service Documents. The
+ * WorkspaceInfo interface provides information used to construct an app:workspace element
+ */
+public interface AtompubWorkspaceInfo 
+  extends WorkspaceInfo {
+
+    /**
+     * Returns an instance of the FOM Workspace interface
+     */
+    Workspace asWorkspaceElement(RequestContext request);
+}

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

Added: abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/model/AtompubWorkspaceManager.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/model/AtompubWorkspaceManager.java?rev=1173209&view=auto
==============================================================================
--- abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/model/AtompubWorkspaceManager.java (added)
+++ abdera/abdera2/server/src/main/java/org/apache/abdera2/protocol/server/model/AtompubWorkspaceManager.java Tue Sep 20 15:56:46 2011
@@ -0,0 +1,30 @@
+/*
+ * 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.model;
+
+import org.apache.abdera2.common.protocol.WorkspaceManager;
+
+/**
+ * The Workspace Manager is used by a Provider to access metadata used to construct Atompub service documents and to
+ * determine the appropriate CollectionAdapter to handle a particular request
+ */
+public interface AtompubWorkspaceManager
+  extends WorkspaceManager{
+
+    
+}

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



Mime
View raw message