/**
* Licensed to The Apereo Foundation under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
*
* The Apereo Foundation licenses this file to you under the Educational
* Community 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://opensource.org/licenses/ecl2.txt
*
* 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.opencastproject.feed.impl;
import org.opencastproject.feed.api.Feed.Type;
import org.opencastproject.mediapackage.MediaPackageElementFlavor;
import org.opencastproject.search.api.SearchResult;
import org.opencastproject.search.api.SearchService;
import org.opencastproject.security.api.SecurityService;
import org.opencastproject.series.api.SeriesService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Properties;
/**
* Convenience implementation that is intended to serve as a base implementation for feed generator services. It handles
* service activation, reads a default set of properties (see below) and can be configured to track the opencast
* {@link SearchService} by using {@link #setSearchService(SearchService)}, {@link SeriesService} by using
* {@link #setSeriesService(SeriesService)} and {@link SecurityService} by using
* {@link #setSecurityService(SecurityService)}.
* <p>
* By using this implementation as the basis for feed services, only the two methods accept and loadFeedData need to be
* implemented by subclasses.
* <p>
* The following properties are being read from the component properties:
* <ul>
* <li><code>feed.uri</code> - the feed uri</li>
* <li><code>feed.selector</code> the pattern that is used to determine if the feed implementation wants to handle a
* request, e. g. the selector {{latest}} in {{http://servername/feeds/atom/0.3/latest}} maps the latest feed handler
* to urls containing that selector</li>
* <li><code>feed.name</code> - name of this feed</li>
* <li><code>feed.description</code> - an abstract of this feed</li>
* <li><code>feed.copyright</code> - the feed copyright note</li>
* <li><code>feed.home</code> - url of the feed's home page</li>
* <li><code>feed.cover</code> - url of the feed's cover image</li>
* <li><code>feed.entry</code> - template to create a link to a feed entry</li>
* <li><code>feed.rssflavor</code> - flavor identifying rss feed media package elements</li>
* <li><code>feed.atomflavors</code> - comma separated list of flavors identifying atom feed media package elements</li>
* <li><code>feed.rsstags</code> - tags identifying rss feed media package elements</li>
* <li><code>feed.atomtags</code> - comma separated list of tags identifying atom feed media package elements</li>
* </ul>
*/
public abstract class AbstractFeedService extends AbstractFeedGenerator {
/** Logging facility */
private static Logger logger = LoggerFactory.getLogger(AbstractFeedService.class);
/** The selector used to match urls */
private String selector = null;
/** The search service */
protected SearchService searchService = null;
/** The search service */
protected SeriesService seriesService = null;
/** The security service */
protected SecurityService securityService = null;
/**
* Creates a new abstract feed generator.
* <p>
* <b>Note:</b> Subclasses using this constructor need to set required member variables prior to calling
* createFeed for the first time.
*/
protected AbstractFeedService() {
super();
}
/**
* Creates a new abstract feed generator.
*
* @param uri
* the feed identifier
* @param feedHome
* the feed's home url
* @param rssFlavors
* the flavors identifying rss tracks
* @param atomFlavors
* the flavors identifying tracks to be included in atom feeds
* @param entryLinkTemplate
* the link template
*/
public AbstractFeedService(String uri, String feedHome, MediaPackageElementFlavor[] rssFlavors,
String[] rssMediaTypes, MediaPackageElementFlavor[] atomFlavors, String entryLinkTemplate) {
super(uri, feedHome, rssFlavors, rssMediaTypes, atomFlavors, entryLinkTemplate);
}
/**
* {@inheritDoc}
*
* @see org.opencastproject.feed.api.FeedGenerator#accept(java.lang.String[])
*/
public boolean accept(String[] query) {
String feedURI = getURI();
if (searchService == null) {
logger.warn("{} denies to handle request for {} due to missing search service", this, query);
return false;
} else if (feedURI == null) {
logger.warn("{} denies to handle request for {} since no uri is defined", this, query);
return false;
} else if (query.length == 0) {
logger.debug("{} denies to handle unknown request", this);
return false;
}
// truncate uri, as it had to be and real uri not an id
String id = extractId(feedURI);
// Check the uri
if (!query[0].equalsIgnoreCase(id)) {
logger.debug("{} denies to handle request for {}", this, query);
return false;
}
// Check the selector
if (selector != null && (query.length < 2 || !query[1].equalsIgnoreCase(selector))) {
return false;
}
logger.debug("{} accepts to handle request for {}", this, query);
return true;
}
protected String extractId(String uri) {
String id = uri.substring(uri.lastIndexOf("/") + 1);
if (id == null)
return uri;
return id;
}
/**
* {@inheritDoc}
*
* @see org.opencastproject.feed.impl.AbstractFeedGenerator#loadFeedData(org.opencastproject.feed.api.Feed.Type,
* java.lang.String[], int, int)
*/
protected abstract SearchResult loadFeedData(Type type, String[] query, int limit, int offset);
/**
* {@inheritDoc}
*
* @see org.opencastproject.feed.api.FeedGenerator#initialize(java.util.Properties)
*/
@Override
public void initialize(Properties properties) {
super.initialize(properties);
selector = (String) properties.get(PROP_SELECTOR);
}
/**
* Returns the feed query.
*
* @return the query
*/
protected String getSelector() {
return selector;
}
/**
* Sets the selector.
*
* @param selector
* the new selector
*/
protected void setSelector(String selector) {
this.selector = selector;
}
/**
* {@inheritDoc}
*
* @see org.opencastproject.feed.impl.AbstractFeedGenerator#hashCode()
*/
@Override
public int hashCode() {
return super.hashCode();
}
/**
* {@inheritDoc}
*
* @see org.opencastproject.feed.impl.AbstractFeedGenerator#equals(java.lang.Object)
*/
@Override
public boolean equals(Object o) {
if (!(o instanceof AbstractFeedService) || selector == null)
return super.equals(o);
return super.equals(o) && selector.equals(((AbstractFeedService) o).selector);
}
/**
* Sets the search service.
*
* @param searchService
* the search service
*/
public void setSearchService(SearchService searchService) {
this.searchService = searchService;
}
/**
* Returns the search service.
*
* @return the search services
*/
protected SearchService getSearchService() {
return searchService;
}
/**
* Sets the series service.
*
* @param seriesService
* the series service
*/
public void setSeriesService(SeriesService seriesService) {
this.seriesService = seriesService;
}
/**
* Returns the series service.
*
* @return the series services
*/
protected SeriesService getSeriesService() {
return seriesService;
}
/**
* Sets the security service.
*
* @param securityService
* the security service
*/
public void setSecurityService(SecurityService securityService) {
this.securityService = securityService;
}
/**
* Returns the security service.
*
* @return the security services
*/
protected SecurityService getSecurityService() {
return securityService;
}
}