/*
* Copyright 2012 Eric F. Savage, code@efsavage.com
*
* 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 com.ajah.syndicate.data;
import java.util.Date;
import java.util.UUID;
import lombok.extern.java.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ajah.spring.jdbc.err.DataOperationException;
import com.ajah.syndicate.FeedSource;
import com.ajah.syndicate.FeedSourceId;
import com.ajah.syndicate.FeedSourceStatus;
import com.ajah.syndicate.FeedSourceType;
import com.ajah.syndicate.PollStatus;
import com.ajah.util.data.HashUtils;
/**
* Manages persistence of {@link FeedSource}s.
*
* @author <a href="http://efsavage.com">Eric F. Savage</a>, <a
* href="mailto:code@efsavage.com">code@efsavage.com</a>.
*
*/
@Service
@Log
public class FeedSourceManager {
@Autowired
private FeedSourceDao feedSourceDao;
/**
* Creates a new source.
*
* @param url
* The URL of the {@link FeedSource}.
* @return The new source.
* @throws DataOperationException
* If a query could not be executed.
*/
private FeedSource create(final String url) throws DataOperationException {
final FeedSource feedSource = new FeedSource();
feedSource.setFeedUrl(url);
feedSource.setTitle(url);
feedSource.setFeedUrlSha1(HashUtils.sha1Hex(url));
feedSource.setPollStatus(PollStatus.ACTIVE);
feedSource.setType(FeedSourceType.RSS);
feedSource.setStatus(FeedSourceStatus.ACTIVE);
feedSource.setNextPoll(new Date());
save(feedSource);
return feedSource;
}
/**
* Finds a feed by it's full URL.
*
* @param url
* The URL of the {@link FeedSource}.
* @return The matching source, if found.
* @throws DataOperationException
* If a query could not be executed.
*/
public FeedSource findByFeedUrl(final String url) throws DataOperationException {
return findByFeedUrlSha1(HashUtils.sha1Hex(url));
}
/**
* Finds a feed source by the SHA-1 of the feed url.
*
* @param feedUrlSha1
* The SHA-1 of the feed url.
* @return The feed source, if found, otherwise null.
* @throws DataOperationException
* If a query could not be executed.
*/
public FeedSource findByFeedUrlSha1(final String feedUrlSha1) throws DataOperationException {
return this.feedSourceDao.findByFeedUrlSha1(feedUrlSha1);
}
/**
* Attempts to find a matching feed source, and creates a new one if
* necessary.
*
* @param candidate
* The candidate source to me matched or saved.
* @return The matched or saved feed source.
* @throws DataOperationException
* If a query could not be executed.
*/
public FeedSource findOrCreate(final FeedSource candidate) throws DataOperationException {
FeedSource feedSource = findByFeedUrlSha1(HashUtils.sha1Hex(candidate.getFeedUrl()));
if (feedSource == null) {
feedSource = candidate;
save(feedSource);
} else {
log.fine("Duplicate feed found");
// TODO Update other information?
}
return feedSource;
}
/**
* Finds a feed by it's full URL. If none is found, creates a new one.
*
* @param url
* The URL of the {@link FeedSource}.
* @return The new or matching source.
* @throws DataOperationException
* If a query could not be executed.
*/
public FeedSource findOrCreateByFeedUrl(final String url) throws DataOperationException {
FeedSource feedSource = findByFeedUrlSha1(HashUtils.sha1Hex(url));
if (feedSource == null) {
feedSource = create(url);
}
return feedSource;
}
/**
* Find a feed source where the next_poll_date field is in the past.
*
* @return A feed source where the next_poll_date field is in the past, if
* available, otherwise null.
* @throws DataOperationException
*/
public FeedSource getStaleFeedSource() throws DataOperationException {
return this.feedSourceDao.getStaleFeedSource();
}
/**
* Loads an feed source by its ID.
*
* @param feedSourceId
* The ID to load.
* @return The feed source, will not be null.
* @throws DataOperationException
* If the query could not be executed.
* @throws FeedSourceNotFoundException
* If no feed source could be found with the specified ID.
*/
public FeedSource load(final FeedSourceId feedSourceId) throws DataOperationException, FeedSourceNotFoundException {
final FeedSource feedSource = this.feedSourceDao.load(feedSourceId);
if (feedSource == null) {
throw new FeedSourceNotFoundException(feedSourceId);
}
return feedSource;
}
/**
* Saves a feed source, inserting if the ID is empty, otherwise updating.
*
* @param feedSource
* The feed source to save.
* @throws DataOperationException
* If the feed source could not be saved.
*/
public void save(final FeedSource feedSource) throws DataOperationException {
if (feedSource.getNextPoll() == null) {
feedSource.setNextPoll(new Date());
}
if (feedSource.getId() == null) {
feedSource.setId(new FeedSourceId(UUID.randomUUID().toString()));
feedSource.setCreated(new Date());
feedSource.setModified(feedSource.getCreated());
this.feedSourceDao.insert(feedSource);
} else {
feedSource.setModified(new Date());
this.feedSourceDao.update(feedSource);
}
}
}