package org.atomhopper.abdera;
import org.apache.abdera.Abdera;
import org.apache.abdera.model.Entry;
import org.apache.abdera.model.Feed;
import org.apache.abdera.parser.ParseException;
import org.apache.abdera.protocol.server.ProviderHelper;
import org.apache.abdera.protocol.server.RequestContext;
import org.apache.abdera.protocol.server.ResponseContext;
import org.apache.abdera.protocol.server.TargetType;
import org.apache.commons.lang.StringUtils;
import org.atomhopper.abdera.filter.AdapterResponseInterceptor;
import org.atomhopper.abdera.filter.FeedEntityTagProcessor;
import org.atomhopper.abdera.filter.FeedPagingProcessor;
import org.atomhopper.abdera.response.EmptyBodyResponseHandler;
import org.atomhopper.abdera.response.EntryResponseHandler;
import org.atomhopper.abdera.response.FeedResponseHandler;
import org.atomhopper.abdera.response.ResponseHandler;
import org.atomhopper.adapter.FeedPublisher;
import org.atomhopper.adapter.FeedSource;
import org.atomhopper.adapter.impl.DisabledFeedSource;
import org.atomhopper.adapter.impl.DisabledPublisher;
import org.atomhopper.adapter.request.adapter.GetCategoriesRequest;
import org.atomhopper.adapter.request.adapter.GetFeedRequest;
import org.atomhopper.adapter.request.adapter.impl.*;
import org.atomhopper.config.v1_0.FeedConfiguration;
import org.atomhopper.response.AdapterResponse;
import org.atomhopper.response.EmptyBody;
import org.springframework.http.HttpStatus;
import java.util.*;
public class FeedAdapter extends TargetAwareAbstractCollectionAdapter {
private final ResponseHandler<EmptyBody> emptyBodyResponseHandler;
private final ResponseHandler<Feed> feedResponseHandler;
private final ResponseHandler<Entry> entryResponseHandler;
private final FeedConfiguration feedConfiguration;
private final FeedPublisher feedPublisher;
private final FeedSource feedSource;
public FeedAdapter(String target, FeedConfiguration feedConfiguration, FeedSource feedSource, FeedPublisher feedPublisher,
List<AdapterResponseInterceptor<Feed>>adapterResponseInterceptorList) {
super(target);
if ( adapterResponseInterceptorList == null ) {
throw new IllegalArgumentException("adapterResponseInterceptorList argument must not be null");
}
this.feedConfiguration = feedConfiguration;
final List<String> allowedMethodsList = new LinkedList<String>();
if (feedSource != null) {
this.feedSource = feedSource;
allowedMethodsList.add("GET");
} else {
this.feedSource = DisabledFeedSource.getInstance();
}
if (feedPublisher != null) {
this.feedPublisher = feedPublisher;
allowedMethodsList.add("PUT");
allowedMethodsList.add("POST");
allowedMethodsList.add("DELETE");
} else {
this.feedPublisher = DisabledPublisher.getInstance();
}
final String[] allowedMethods = allowedMethodsList.toArray(new String[allowedMethodsList.size()]);
feedResponseHandler = new FeedResponseHandler(allowedMethods, adapterResponseInterceptorList);
entryResponseHandler = new EntryResponseHandler(allowedMethods);
emptyBodyResponseHandler = new EmptyBodyResponseHandler(allowedMethods);
}
public FeedAdapter(String target, FeedConfiguration feedConfiguration, FeedSource feedSource, FeedPublisher feedPublisher,
AdapterResponseInterceptor<Feed>...interceptors) {
this(target, feedConfiguration, feedSource, feedPublisher, Arrays.asList(interceptors));
}
public FeedAdapter(String target, FeedConfiguration feedConfiguration, FeedSource feedSource, FeedPublisher feedPublisher) {
this(target, feedConfiguration, feedSource, feedPublisher, new FeedPagingProcessor(), new FeedEntityTagProcessor());
}
public FeedConfiguration getFeedConfiguration() {
return feedConfiguration;
}
@Override
public String getHref(RequestContext request) {
final Map<String, Object> params = new HashMap<String, Object>();
params.put("collection", getTarget());
return request.urlFor(TargetType.TYPE_COLLECTION, params);
}
@Override
public String getAuthor(RequestContext request) {
return getFeedConfiguration().getAuthor().getName();
}
@Override
public ResponseContext getCategories(RequestContext request) {
final GetCategoriesRequest getCategoriesRequest = new GetCategoriesRequestImpl(request);
try {
return ProviderHelper
.returnBase(feedSource.getFeedInformation().getCategories(getCategoriesRequest), HttpStatus.OK.value(), Calendar.getInstance().getTime());
} catch (Exception ex) {
return ProviderHelper.servererror(request, ex.getMessage(), ex);
}
}
@Override
public String getId(RequestContext request) {
return feedSource.getFeedInformation().getId(new GetFeedRequestImpl(request));
}
@Override
public String getTitle(RequestContext request) {
return getFeedConfiguration().getTitle();
}
@Override
public ResponseContext getFeed(RequestContext request) {
GetFeedRequest getFeedRequest = new GetFeedRequestImpl(request);
final String limitErrorMessage = "Limit parameter not valid, acceptable values are 1 to 1000";
final int minLimit = 1;
final int maxLimit = 1000;
try {
final String pageSizeString = getFeedRequest.getPageSize();
if ((StringUtils.isNotBlank(pageSizeString)) && ((Integer.parseInt(pageSizeString) < minLimit) || (Integer.parseInt(pageSizeString) > maxLimit))) {
return ProviderHelper.badrequest(request, limitErrorMessage);
}
} catch (NumberFormatException nfe) {
return ProviderHelper.badrequest(request, limitErrorMessage);
}
try {
return feedResponseHandler.handleResponse(request, feedSource.getFeed(getFeedRequest));
} catch (Exception ex) {
return ProviderHelper.servererror(request, ex.getMessage(), ex);
}
}
@Override
public ResponseContext postEntry(RequestContext request) {
try {
final AdapterResponse<Entry> response = feedPublisher.postEntry(new PostEntryRequestImpl(request));
if (response.getBody() != null && response.getBody().getSelfLinkResolvedHref() != null) {
return entryResponseHandler.handleResponse(request, response).addHeader("Location", response.getBody().getSelfLinkResolvedHref().toString());
} else {
return entryResponseHandler.handleResponse(request, response);
}
} catch (ParseException ex) {
return ProviderHelper.createErrorResponse(Abdera.getInstance(), HttpStatus.UNPROCESSABLE_ENTITY.value(), ex.getMessage(), ex);
} catch (RequestParsingException rpex) {
return ProviderHelper
.createErrorResponse(Abdera.getInstance(), HttpStatus.UNPROCESSABLE_ENTITY.value(), "The POST did not contain valid ATOM XML", rpex);
} catch (IllegalArgumentException iae) {
return ProviderHelper.badrequest(request, iae.getMessage());
} catch (Exception ex) {
return ProviderHelper.servererror(request, ex.getMessage(), ex);
}
}
@Override
public ResponseContext putEntry(RequestContext request) {
try {
final AdapterResponse<Entry> response = feedPublisher.putEntry(new PutEntryRequestImpl(request));
return entryResponseHandler.handleResponse(request, response);
} catch (Exception ex) {
return ProviderHelper.servererror(request, ex.getMessage(), ex);
}
}
@Override
public ResponseContext deleteEntry(RequestContext request) {
try {
final AdapterResponse<EmptyBody> response = feedPublisher.deleteEntry(new DeleteEntryRequestImpl(request));
return emptyBodyResponseHandler.handleResponse(request, response);
} catch (Exception ex) {
return ProviderHelper.servererror(request, ex.getMessage(), ex);
}
}
@Override
public ResponseContext getEntry(RequestContext request) {
try {
return entryResponseHandler.handleResponse(request, feedSource.getEntry(new GetEntryRequestImpl(request)));
} catch (Exception ex) {
return ProviderHelper.servererror(request, ex.getMessage(), ex);
}
}
}