package esl.cuenet.algorithms.firstk.personal.accessor;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import esl.cuenet.algorithms.firstk.personal.EventContextNetwork;
import esl.cuenet.algorithms.firstk.personal.Location;
import esl.cuenet.algorithms.firstk.personal.Time;
import esl.cuenet.query.drivers.mongodb.MongoDB;
import org.apache.log4j.Logger;
import java.io.FileWriter;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
public class Facebook implements Source {
private Logger logger = Logger.getLogger(Facebook.class);
private Candidates candidateList = Candidates.getInstance();
private Multimap<Candidates.CandidateReference, Candidates.CandidateReference> knowsGraph = HashMultimap.create();
private List<FBEvent> events = Lists.newArrayList();
private List<FBPhoto> photos = Lists.newArrayList();
protected Facebook() {
FBLoader loader = new FBLoader();
loader.load();
}
private static Facebook instance = new Facebook();
public static Facebook getInstance() {
return instance;
}
@Override
public List<EventContextNetwork> eventsContaining(Candidates.CandidateReference person, Time interval, Location location) {
List<EventContextNetwork> nets = null;
for (FBEvent event: events) {
if (event.time.contains(interval) && event.participants.contains(person)) {
if (nets == null) nets = Lists.newArrayList();
addToNets(nets, event, location);
}
}
if (nets != null && nets.size() > 0) logger.info("Found " + nets.size() + " facebook event.");
return nets;
}
private void addToNets(List<EventContextNetwork> nets, FBEvent event, Location location) {
if (event.sent) return;
EventContextNetwork network = new EventContextNetwork();
EventContextNetwork.ECNRef eventRef = network.createEvent("event", event.time.getStart(), event.time.getEnd(), location.getFullAddress());
network.initializeSubeventTree(eventRef);
for (Candidates.CandidateReference candidate: event.participants) {
EventContextNetwork.ECNRef pRef = network.createPerson(candidate);
network.createPartiticipationEdge(eventRef, pRef);
}
event.sent = true;
nets.add(network);
}
@Override
public List<EventContextNetwork> participants(EventContextNetwork.Event event) {
return null;
}
@Override
public List<EventContextNetwork> subevents(EventContextNetwork.Event event) {
return null;
}
@Override
public List<Candidates.CandidateReference> knows(Candidates.CandidateReference person) {
if ( !knowsGraph.containsKey(person) ) return null;
return Lists.newArrayList(knowsGraph.get(person));
}
@Override
public List<EventContextNetwork> knowsAtTime(Candidates.CandidateReference person, Time time) {
return null;
}
@Override
public void writeInstances(FileWriter instanceFileWriter) throws IOException {
int instance_count = 0;
int event_id = 8;
for (FBPhoto obj: photos) {
instance_count++;
instanceFileWriter.write(event_id + " " + instance_count);
instanceFileWriter.write('\n');
instanceFileWriter.write(event_id + ", " + obj.participants.toString() + ", " + (obj.time.getStart() + obj.time.getEnd())/2);
instanceFileWriter.write('\n');
instanceFileWriter.write("====================================\n");
}
}
class FBEvent {
Time time;
BasicDBObject information;
List<Candidates.CandidateReference> participants;
boolean sent = false;
}
class FBPhoto {
Time time;
String id;
List<Candidates.CandidateReference> participants;
}
public class FBLoader extends MongoDB {
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
public FBLoader() {
super(PConstants.DBNAME);
}
public void load() {
//load users
MongoDB.DBReader reader = startReader("fb_users");
reader.getAll(new BasicDBObject());
String name= null, location=null, id=null, email=null;
while (reader.hasNext()) {
BasicDBObject obj = (BasicDBObject) reader.next();
name = obj.getString("name").toLowerCase();
if (obj.containsField("email"))
email = obj.getString("email").toLowerCase();
if (obj.containsField("location")) {
BasicDBObject l = (BasicDBObject) obj.get("location");
if (l.containsField("name"))
location = l.getString("name");
}
id = obj.getString("id");
//logger.info("user = " + name + " " + id + " " + location );
List<String> keys = Lists.newArrayList();
List<String> values = Lists.newArrayList();
keys.add(Candidates.FB_ID_KEY); values.add(id);
if (name != null) {
keys.add(Candidates.NAME_KEY); values.add(name);
}
if (location != null) {
keys.add(Candidates.LOCATION_KEY); values.add(location);
}
if (email != null) {
keys.add(Candidates.EMAIL_KEY); values.add(email);
}
candidateList.createEntity(keys, values);
/*
cReference = candidateList.search(Candidates.NAME_KEY, name);
if (cReference.equals(Candidates.UNKNOWN)) cReference = candidateList.search(Candidates.FB_ID_KEY, id);
if (cReference == Candidates.UNKNOWN && email != null) cReference = candidateList.search(Candidates.EMAIL_KEY, email);
if (cReference == Candidates.UNKNOWN) cReference = candidateList.createCandidate(Candidates.FB_ID_KEY, id);
if (name != null) candidateList.add(cReference, Candidates.NAME_KEY, name);
if (email != null) candidateList.add(cReference, Candidates.EMAIL_KEY, email);
if (location != null) candidateList.add(cReference, Candidates.LOCATION_KEY, location);
*/
//re-init to null
location=null; email=null;
}
//relations
reader = startReader("fb_relationships");
reader.getAll(new BasicDBObject());
String pid = null, relationid = null;
while (reader.hasNext()) {
BasicDBObject obj = (BasicDBObject) reader.next();
relationid = obj.getString("relation");
pid = obj.getString("id");
//logger.info("relationships = " + pid + " " + relationid);
List<Candidates.CandidateReference> relRef = candidateList.search(Candidates.FB_ID_KEY, relationid);
List<Candidates.CandidateReference> selfRef = candidateList.search(Candidates.FB_ID_KEY, pid);
if (relRef.size() != 1) throw new NullPointerException();
if (selfRef.size() != 1) throw new NullPointerException();
knowsGraph.put(relRef.get(0), selfRef.get(0));
knowsGraph.put(selfRef.get(0), relRef.get(0));
}
//events
reader = startReader("fb_events");
reader.getAll(new BasicDBObject());
long start=0, end=0;
while (reader.hasNext()) {
BasicDBObject obj = (BasicDBObject) reader.next();
FBEvent fbEvent = new FBEvent();
start = (Long.parseLong(obj.getString("start_time")) + 0 * 3600) * 1000;
end = (Long.parseLong(obj.getString("end_time")) + 0 * 3600) * 1000;
fbEvent.time = Time.createFromInterval(start, end);
fbEvent.information = new BasicDBObject();
fbEvent.information.put("eid", obj.getString("eid"));
if (obj.containsField("name")) fbEvent.information.put("title", obj.getString("name"));
if (obj.containsField("location")) fbEvent.information.put("location", obj.getString("location"));
if (obj.containsField("description")) fbEvent.information.put("description", obj.getString("description"));
events.add(fbEvent);
}
logger.info("Loaded " + events.size() + " events.");
for (FBEvent e: events) loadAttendees(e);
//loadPhotos();
close();
}
private void loadPhotos() {
logger.info("Loading FB Photos");
DBReader reader = this.startReader("fb_photos");
BasicDBObject keys = new BasicDBObject();
keys.put("_id", 0);
reader.getAll(keys);
String tagId, tagName, date;
while (reader.hasNext()) {
BasicDBObject obj = (BasicDBObject) reader.next();
if ( !obj.containsField("created_time") ) {
logger.error("object doesn't have 'created_time' field: " + obj);
continue;
}
date = obj.getString("created_time");
long t = parseFBDate(date).getTime();
FBPhoto photo = new FBPhoto();
photo.time = Time.createFromMoment(t);
photo.participants = Lists.newArrayList();
if (obj.containsField("tags")) {
BasicDBObject _tags = (BasicDBObject) obj.get("tags");
if (_tags.containsField("data")) {
for (Object o: (BasicDBList) _tags.get("data")) {
tagId = null; tagName = null;
BasicDBObject tag = (BasicDBObject) o;
if (tag.containsField("id")) tagId = tag.getString("id");
Candidates.CandidateReference ref = candidateList.searchLimitOne(Candidates.FB_ID_KEY, tagId);
if (ref == Candidates.UNKNOWN || ref == null) continue;
photo.participants.add(ref);
}
}
}
photos.add(photo);
}
logger.info("Loaded " + photos.size() + " Photos");
}
private Date parseFBDate(String sDate) {
if (sDate == null) return new Date(0);
Date dt;
try {
dt = dateFormat.parse(sDate);
} catch (ParseException e) {
logger.error("Date couldn't be parsed: " + sDate);
logger.error("MESSAGE: " + e.getMessage());
dt = new Date(0);
}
return dt;
}
private void loadAttendees(FBEvent event) {
MongoDB.DBReader reader = startReader("fb_event_attendees");
reader.query(new BasicDBObject("eid", event.information.get("eid")));
event.participants = Lists.newArrayList();
while(reader.hasNext()) {
BasicDBObject obj = (BasicDBObject) reader.next();
Candidates.CandidateReference ref = candidateList.searchLimitOne(Candidates.FB_ID_KEY, obj.getString("id"));
if (ref == null) {
logger.info("Ref = null for id " + obj.getString("name"));
continue;
}
event.participants.add(ref);
}
if (event.participants.size() > 0)
logger.info("Event has " + event.participants.size() + " attendees");
}
}
}