/* * Copyright (c) 2007-2014 by Public Library of Science * * http://plos.org * http://ambraproject.org * * Licensed 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. */ package org.ambraproject.action.feed; import com.opensymphony.xwork2.ModelDriven; import org.ambraproject.ApplicationException; import org.ambraproject.action.BaseActionSupport; import org.ambraproject.service.feed.AnnotationFeedSearchParameters; import org.ambraproject.service.feed.FeedSearchParameters; import org.ambraproject.service.feed.FeedService; import org.ambraproject.service.feed.FeedService.FEED_TYPES; import org.ambraproject.views.AnnotationView; import org.ambraproject.views.LinkbackView; import org.ambraproject.views.TOCArticle; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Required; import org.w3c.dom.Document; import java.util.List; /** * The <code>class FeedAction</code> provides an API for criteria based retrieval of articles and article information. * The <code>class FeedAction</code> implements the Struts ModelDrive interface. The data model used for * <code>FeedAction</code> is <code>FeedSearchParameters</code>. The field <code>FeedAction.searchParameters</code> is * accessible to Struts through the <code>FeedAction.getModel</code> and <code>FeedAction.getSearchParameters</code> * bean getter. The ModelDriven Interceptor parses the input parameters, converts them to the appropriate Java types * then assigns them to fields in the data model. * <p/> * <p/> * The <code>FeedAction.SearchParameters</code> serves the following purposes: <ul> <li> Receives and validates the * parameters passed in during a Post/Get. <li> Used to pass these parameters to AmbraFeedResult via the ValueStack. * </ul> * <p/> * <p/> * ArticleFeed implements the <code>FeedAction.execute</code> and <code>FeedSearchParameters.validate </code> Struts * entry points. The <code>FeedSearchParameters.validate</code> method assigns default values to fields not provided by * user input and checks parameters that are provided by the user. By the time Struts invokes the * <code>FeedAction.execute</code> all model data variables should be in a known and acceptable state for execution. * <p/> * <p/> * <ul> <li>Define a hard limit of 200 articles returned in one query. <li>If startDate > endDate then startDate set * to endDate. </ul> * <p/> * <h4>Action URI</h4> http://.../article/feed <h4>Parameters</h4> * <pre> * <strong> * Param Format Required Default Description </strong> * startDate ISO yyyy-MM-dd No -3 months Start Date - search for articles * dated >= to sDate * endDate ISO yyyy-MM-dd No today End Date - search for articles * dated <= to eDate * category String No none Article Category * author String No none Article Author name ex: John+Smith * relLinks Boolean No false If relLinks=true; internal links will be * relative to xmlbase * extended Boolean No false If extended=true; provide additional feed * information * title String No none Sets the title of the feed * selfLink String No none URL of feed that is to be put in the feed * data. * IssueURI String Yes none Issue URI (Required for type=Issue only) * maxResults Integer No 30 The maximun number of result to return. * type String No Article Article,Annotation,Comment,Issue * mostViewed Boolean No False Parameter to enable list of most viewed articles * * </pre> * * @author Jeff Suttor * @author Eric Brown * @author Joe Osowski * @see org.ambraproject.service.feed.FeedSearchParameters * @see org.ambraproject.struts2.AmbraFeedResult */ @SuppressWarnings("UnusedDeclaration") public class FeedAction extends BaseActionSupport implements ModelDriven { private static final Logger log = LoggerFactory.getLogger(FeedAction.class); private FeedService feedService; // Feed Service Spring injected. private FeedSearchParameters searchParams; // The action data model private List<TOCArticle> articles; // List of Article IDs; result of search private List<AnnotationView> annotations; // List of Annotations; result of search private List<LinkbackView> trackbacks; // List of tracks; results of search private Document resultFromSolr; // list of articles for the rss feed /** * Try and find the query in the feed cache or query the Article OTM Service if nothing is found. The parameters are * valid by this point. * * @throws Exception Exception */ public String execute() throws Exception { FEED_TYPES t = searchParams.feedType(); String status = SUCCESS; switch (t) { case Annotation: //Trackbacks are (logically but not physically) a form of annotation, if this type of feed is selected //We wanted it included trackbacks = feedService.getTrackbacks(new AnnotationFeedSearchParameters(searchParams)); case Comment: case Reply: //The getAnnotations method performs filters for all of the above types. //(Or not if Annotation is selected) AnnotationFeedSearchParameters will not populate the annotationTypes property //If the type specified is Annotation. It's also worth noting here, while annotationTypes is a collection //We never allow more then one value to be specified currently though a lot of the code supports it annotations = feedService.getAnnotations(new AnnotationFeedSearchParameters(searchParams)); break; case Trackback: trackbacks = feedService.getTrackbacks(new AnnotationFeedSearchParameters(searchParams)); break; case Article: resultFromSolr = feedService.getArticles(searchParams); if (resultFromSolr == null) { status = ERROR; } break; case Issue: articles = feedService.getIssueArticles(searchParams, getCurrentJournal(), getAuthId()); break; } return status; } /** * RSS search feed for Simple/Advanced search. * * @return * @throws ApplicationException */ public String executeFeedSearch() throws ApplicationException { String status = SUCCESS; resultFromSolr = feedService.getSearchArticles(searchParams); if (resultFromSolr == null) { status = ERROR; } return status; } /** * Validate the input parameters or create defaults when they are not provided. Struts calls this automagically after * the parameters are parsed and the proper fields are set in the data model. It is assumed that all necessary fields * are checked for validity and created if not specified. The <code>ArticleFeed.execute</code> should be able to use * them without any further checks. */ @Override public void validate() { /* * The searchParams must have both the current Journal and start date. Current Journal is set here * and startDate will be set in the data model validator. */ searchParams.setJournal(getCurrentJournal()); searchParams.validate(this); if (log.isErrorEnabled()) { for (Object key : getFieldErrors().keySet()) { log.error("Validate error: " + getFieldErrors().get(key) + " on " + key + " for searchParams: " + searchParams); } } } /** * Set <code>feedService</code> field to the article Feed service singleton. * * @param feedService the object transaction model reference */ @Required public void setFeedService(final FeedService feedService) { this.feedService = feedService; } /** * This is the results of the query which consist of a list of article or annotation ID's. * * @return the list of article/annotation ID's returned from the query. */ public List<TOCArticle> getArticles() { return articles; } /** * This is the results of the query which consist of a list of annotations. * * @return the list of article/annotation ID's returned from the query. */ public List<AnnotationView> getAnnotations() { return annotations; } /** * This is the results of the query which consist of a list of trackbacks. * * @return the list of article/annotation ID's returned from the query. */ public List<LinkbackView> getTrackbacks() { return trackbacks; } /** * Return the search parameters being used by this action. * * @return Key to the cache which is also the data model of the action */ public FeedSearchParameters getSearchParameters() { return this.searchParams; } /** * Return the search parameters which is also the data model for the model driven interface. * * @return searchParams which is also the data model of the action */ public Object getModel() { /* * getModel is invoked several times by different interceptors * Make sure caheKey is not created twice. */ return (searchParams == null) ? searchParams = feedService.newSearchParameters() : searchParams; } /** * Returns the solr search result that contains the list of articles * * @return solr search result */ public Document getResultFromSolr() { return resultFromSolr; } }