package qa.qcri.aidr.collector.api;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ws.rs.core.Response;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
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.FacebookCollectionTask;
import qa.qcri.aidr.collector.beans.FacebookProfile;
import qa.qcri.aidr.collector.beans.ResponseWrapper;
import qa.qcri.aidr.collector.collectors.FacebookFeedTracker;
import qa.qcri.aidr.collector.service.CollectionService;
import qa.qcri.aidr.collector.utils.CollectorConfigurationProperty;
import qa.qcri.aidr.collector.utils.CollectorConfigurator;
import qa.qcri.aidr.collector.utils.GenericCache;
@RestController
@RequestMapping("/facebook")
public class FacebookCollectionController extends BaseController<FacebookCollectionTask> {
private static Logger logger = Logger.getLogger(FacebookCollectionController.class);
private static CollectorConfigurator configProperties = CollectorConfigurator.getInstance();
@Autowired
CollectionService collectionService;
@RequestMapping(value = "/start", method={RequestMethod.POST})
public Response startCollection(@RequestBody FacebookCollectionTask task) {
ResponseWrapper response = new ResponseWrapper();
//check if all fb specific information is available in the request
if (!task.checkSocialConfigInfo()) {
response.setStatusCode(configProperties.getProperty(CollectorConfigurationProperty.STATUS_CODE_COLLECTION_ERROR));
response.setMessage("One or more Facebook 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()) {
response.setStatusCode(configProperties.getProperty(CollectorConfigurationProperty.STATUS_CODE_COLLECTION_ERROR));
response.setMessage("Missing one or more fields (toTrack & toFollow). 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 {
FacebookFeedTracker tracker = new FacebookFeedTracker(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.setFbConfigMap(cacheKey, task);
cache.setFacebookTracker(cacheKey, tracker);
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 failedTask = GenericCache.getInstance().getFailedCollectionTask(id);
if (failedTask != null) {
Response stopTaskResponse = stopCollection(id);
if(stopTaskResponse == null) {
ResponseWrapper responseWrapper = new ResponseWrapper();
responseWrapper.setMessage("Invalid key. No running collector found for the given id.");
responseWrapper.setStatusCode(configProperties.getProperty(CollectorConfigurationProperty.STATUS_CODE_COLLECTION_NOTFOUND));
stopTaskResponse = Response.ok(responseWrapper).build();
}
return stopTaskResponse;
}
FacebookCollectionTask task = GenericCache.getInstance().getFacebookConfig(id);
if (task != null) {
return Response.ok(task).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(value = "/searchProfiles", method={RequestMethod.POST})
public Response searchProfiles(@RequestBody String accessToken, @RequestParam String keyword,
@RequestParam Integer limit, @RequestParam Integer offset) {
FacebookFeedTracker tracker = new FacebookFeedTracker(accessToken);
List<FacebookProfile> fbProfiles = tracker.searchProfiles(keyword, limit, offset);
Response.ok(fbProfiles).build();
return Response.ok(fbProfiles).build();
}
@RequestMapping("/rerun")
public Map<String, String> rerunCollection(@RequestParam("code") String code) {
if(GenericCache.getInstance().getFbConfigMap(code) != null
&& !GenericCache.getInstance().getFbConfigMap(code).isPullInProgress()) {
FacebookFeedTracker tracker = GenericCache.getInstance().getFacebookTracker(code);
tracker.start();
logger.info("Collection " + code + " started.");
}
Map<String, String> message = new HashMap<String, String>();
message.put("message", "SUCCESS");
return message;
}
protected Response stopCollection(String collectionCode) {
GenericCache cache = GenericCache.getInstance();
cache.setFbSyncStateMap(collectionCode, 1);
FacebookFeedTracker tracker = cache.getFacebookTracker(collectionCode);
FacebookCollectionTask task = cache.getFacebookConfig(collectionCode);
cache.delFbSyncObjMap(collectionCode);
cache.delFbSyncStateMap(collectionCode);
cache.delFailedCollection(collectionCode);
cache.deleteCounter(collectionCode);
cache.delFbConfigMap(collectionCode);
cache.delLastDownloadedDoc(collectionCode);
cache.delFacebookTracker(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;
}
}