package qa.qcri.aidr.collector.api;
import java.io.IOException;
import java.util.List;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import qa.qcri.aidr.collector.beans.CollectionTask;
import qa.qcri.aidr.collector.beans.ResponseWrapper;
import qa.qcri.aidr.collector.beans.TwitterCollectionTask;
import qa.qcri.aidr.collector.collectors.TwitterStreamTracker;
import qa.qcri.aidr.collector.utils.CollectorConfigurationProperty;
import qa.qcri.aidr.collector.utils.GenericCache;
/**
* @author Imran
* RESTFul APIs to start and stop Twitter collections.
* TODO: remove non-API related operations such as startPersister to other appropriate classes.
*/
@RestController
@RequestMapping("/twitter")
public class TwitterCollectionController extends BaseController {
@RequestMapping(value = "/start", method={RequestMethod.POST})
public Response startTask(@RequestBody TwitterCollectionTask task) {
logger.info("Collection start request received for " + task.getCollectionCode());
logger.info("Details:\n" + task.toString());
ResponseWrapper response = new ResponseWrapper();
//check if all twitter specific information is available in the request
if (!task.checkSocialConfigInfo()) {
response.setStatusCode(configProperties.getProperty(CollectorConfigurationProperty.STATUS_CODE_COLLECTION_ERROR));
response.setMessage("One or more Twitter authentication token(s) are missing");
return Response.ok(response).build();
}
//check if all query parameters are missing in the query
if (!task.isToTrackAvailable() && !task.isToFollowAvailable() && !task.isGeoLocationAvailable()) {
response.setStatusCode(configProperties.getProperty(CollectorConfigurationProperty.STATUS_CODE_COLLECTION_ERROR));
response.setMessage("Missing one or more fields (toTrack, toFollow, and geoLocation). At least one field is required");
return Response.ok(response).build();
}
String collectionCode = task.getCollectionCode();
//check if a task is already running with same configurations
logger.info("Checking OAuth parameters for " + collectionCode);
GenericCache cache = GenericCache.getInstance();
if (cache.isConfigExists(task)) {
String msg = "Provided OAuth configurations already in use. Please stop this collection and then start again.";
logger.info(collectionCode + ": " + msg);
response.setMessage(msg);
response.setStatusCode(configProperties.getProperty(CollectorConfigurationProperty.STATUS_CODE_COLLECTION_ERROR));
return Response.ok(response).build();
}
task.setStatusCode(configProperties.getProperty(CollectorConfigurationProperty.STATUS_CODE_COLLECTION_INITIALIZING));
logger.info("Initializing connection with Twitter streaming API for collection " + collectionCode);
try {
TwitterStreamTracker tracker = new TwitterStreamTracker(task);
tracker.start();
String cacheKey = task.getCollectionCode();
cache.incrCounter(cacheKey, new Long(0));
// if twitter streaming connection successful then change the status
// code
task.setStatusCode(configProperties.getProperty(CollectorConfigurationProperty.STATUS_CODE_COLLECTION_RUNNING));
task.setStatusMessage(null);
cache.setTwitterTracker(cacheKey, tracker);
cache.setTwtConfigMap(cacheKey, task);
if(task.getPersist()!=null){
if(task.getPersist()){
startPersister(collectionCode, task.isSaveMediaEnabled());
}
}
else{
if (Boolean.valueOf(configProperties.getProperty(CollectorConfigurationProperty.DEFAULT_PERSISTANCE_MODE))) {
startPersister(collectionCode, task.isSaveMediaEnabled());
}
}
response.setMessage(configProperties.getProperty(CollectorConfigurationProperty.STATUS_CODE_COLLECTION_INITIALIZING));
response.setStatusCode(configProperties.getProperty(CollectorConfigurationProperty.STATUS_CODE_COLLECTION_INITIALIZING));
} catch (Exception ex) {
logger.error("Exception in creating TwitterStreamTracker for collection " + collectionCode, ex);
response.setMessage(ex.getMessage());
response.setStatusCode(configProperties.getProperty(CollectorConfigurationProperty.STATUS_CODE_COLLECTION_ERROR));
}
return Response.ok(response).build();
}
@RequestMapping("/status")
public Response getStatus(@RequestParam("id") String id) {
ResponseWrapper response = new ResponseWrapper();
if (StringUtils.isEmpty(id)) {
response.setMessage("Invalid key. No running collector found for the given id.");
response.setStatusCode(configProperties.getProperty(CollectorConfigurationProperty.STATUS_CODE_COLLECTION_NOTFOUND));
return Response.ok(response).build();
}
CollectionTask task = GenericCache.getInstance().getTwitterConfig(id);
if (task != null) {
return Response.ok(task).build();
}
CollectionTask failedTask = GenericCache.getInstance().getFailedCollectionTask(id);
if (failedTask != null) {
return Response.ok(failedTask).build();
}
response.setMessage("Invalid key. No running collector found for the given id.");
response.setStatusCode(configProperties.getProperty(CollectorConfigurationProperty.STATUS_CODE_COLLECTION_NOTFOUND));
return Response.ok(response).build();
}
@RequestMapping("/restart")
public ResponseWrapper restartCollection(@QueryParam("code") String collectionCode) throws InterruptedException {
List<CollectionTask> collections = GenericCache.getInstance().getAllRunningCollectionTasks();
CollectionTask collectionToRestart = null;
for (CollectionTask collection : collections) {
if (collection.getCollectionCode().equalsIgnoreCase(collectionCode)) {
collectionToRestart = collection;
break;
}
}
stopTask(collectionCode);
Thread.sleep(3000);
return null;//startTask(collectionToRestart);
}
@RequestMapping("/status/all")
public List<CollectionTask> getStatusAll() {
List<CollectionTask> allTasks = GenericCache.getInstance().getAllConfigs();
return allTasks;
}
@RequestMapping("/failed/all")
public List<CollectionTask> getAllFailedCollections() {
List<CollectionTask> allTasks = GenericCache.getInstance().getAllFailedCollections();
return allTasks;
}
protected Response stopCollection(String collectionCode) {
GenericCache cache = GenericCache.getInstance();
TwitterStreamTracker tracker = cache.getTwitterTracker(collectionCode);
CollectionTask task = cache.getTwitterConfig(collectionCode);
cache.delFailedCollection(collectionCode);
cache.deleteCounter(collectionCode);
cache.delTwtConfigMap(collectionCode);
cache.delLastDownloadedDoc(collectionCode);
cache.delTwitterTracker(collectionCode);
cache.delReconnectAttempts(collectionCode);
if (tracker != null) {
try {
tracker.close();
} catch (IOException e) {
ResponseWrapper response = new ResponseWrapper();
response.setMessage(e.getMessage());
response.setStatusCode(configProperties.getProperty(CollectorConfigurationProperty.STATUS_CODE_COLLECTION_NOTFOUND));
return Response.ok(response).build();
}
if(task.getPersist()!=null){
if(task.getPersist()){
stopPersister(collectionCode);
}
}
else{
if (Boolean.valueOf(configProperties.getProperty(CollectorConfigurationProperty.DEFAULT_PERSISTANCE_MODE))) {
stopPersister(collectionCode);
}
}
logger.info(collectionCode + ": " + "Collector has been successfully stopped.");
} else {
logger.info("No collector instances found to be stopped with the given id:" + collectionCode);
}
if (task != null) {
task.setStatusCode(configProperties.getProperty(CollectorConfigurationProperty.STATUS_CODE_COLLECTION_STOPPED));
return Response.ok(task).build();
}
return null;
}
}