package esl.cuenet.source.accessors;
import com.hp.hpl.jena.enhanced.EnhGraph;
import com.hp.hpl.jena.ontology.Individual;
import com.hp.hpl.jena.ontology.OntModel;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import esl.cuenet.query.IResultIterator;
import esl.cuenet.query.IResultSet;
import esl.cuenet.query.ResultIterator;
import esl.cuenet.query.drivers.mongodb.MongoDB;
import esl.cuenet.source.AccesorInitializationException;
import esl.cuenet.source.Attribute;
import esl.cuenet.source.IAccessor;
import esl.cuenet.source.SourceQueryException;
import esl.datastructures.Location;
import esl.datastructures.TimeInterval;
import org.apache.log4j.Logger;
import javax.mail.internet.MailDateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
public class EmailAccessor extends MongoDB implements IAccessor {
private Logger logger = Logger.getLogger(EmailAccessor.class);
private OntModel model = null;
private Attribute[] attributes = null;
protected boolean[] setFlags = new boolean[3];
protected List<String> queryEmails = new ArrayList<String>(); //Mon, 3 Jan 2011 22:41:28 +0530
private SimpleDateFormat rfc2822DateFormatter = new MailDateFormat();
public EmailAccessor(OntModel model) {
super(AccessorConstants.DBNAME);
this.model = model;
}
@Override
public void setAttributeNames(Attribute[] attributes) throws AccesorInitializationException {
this.attributes = attributes;
}
@Override
public void start() {
for (int i=0; i<setFlags.length; i++) setFlags[i] = false;
queryEmails.clear();
}
@Override
public void associateTimeInterval(Attribute attribute, TimeInterval timeInterval) throws AccesorInitializationException {
throw new AccesorInitializationException("Incorrect Assignment: No time interval attributes in "
+ EmailAccessor.class.getName());
}
@Override
public void associateLocation(Attribute attribute, Location timeInterval) throws AccesorInitializationException {
throw new AccesorInitializationException("Incorrect Assignment: No location attributes in "
+ EmailAccessor.class.getName());
}
@Override
public void associateLong(Attribute attribute, long value) throws AccesorInitializationException {
throw new AccesorInitializationException("Long value being initialized for wrong attribute "
+ EmailAccessor.class.getName());
}
@Override
public void associateString(Attribute attribute, String value) throws AccesorInitializationException {
if (attribute.compareTo(attributes[0])==0) {
setFlags[0] = true;
queryEmails.add(value);
}
else if (attribute.compareTo(attributes[1])==0) {
setFlags[1] = true;
queryEmails.add(value);
}
else if (attribute.compareTo(attributes[2])==0) {
setFlags[2] = true;
queryEmails.add(value);
}
else {
throw new AccesorInitializationException("String value being initialized for wrong attribute "
+ EmailAccessor.class.getName());
}
}
@Override
public void associateDouble(Attribute attribute, double value) throws AccesorInitializationException {
throw new AccesorInitializationException("Long value being initialized for wrong attribute "
+ EmailAccessor.class.getName());
}
@Override
public IResultSet executeQuery() throws SourceQueryException {
return query();
}
private IResultSet query() {
DBReader reader = this.startReader("emails");
ResultSetImpl resultSet = new ResultSetImpl("Email Relations");
BasicDBList emailPredicates = new BasicDBList();
if ( !setFlags[0] && !setFlags[1] && !setFlags[2] ) {
logger.info("No flags set. Empty return set");
return resultSet;
}
BasicDBList predicates = new BasicDBList();
for (String em: queryEmails) {
Pattern emPattern = Pattern.compile(em, Pattern.CASE_INSENSITIVE);
predicates.add(new BasicDBObject("to", emPattern));
predicates.add(new BasicDBObject("from", emPattern));
predicates.add(new BasicDBObject("cc", emPattern));
}
BasicDBObject keys = new BasicDBObject();
keys.put("to", 1);
keys.put("cc", 1);
keys.put("from", 1);
keys.put("date", 1);
keys.put("_id", 0);
BasicDBObject queryObject = new BasicDBObject("$or", predicates);
reader.query(queryObject, keys);
logger.info("Query: " + queryObject);
int c = 0;
String date, to, from, cc;
while (reader.hasNext()) {
BasicDBObject obj = (BasicDBObject) reader.next();
List<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>();
to = obj.getString("to");
if (to != null) entries.addAll(Utils.parseEmailAddresses(to));
from = obj.getString("from");
if (from != null) entries.addAll(Utils.parseEmailAddresses(from));
cc = obj.getString("cc");
if (cc != null)entries.addAll(Utils.parseEmailAddresses(cc));
List<Individual> individualCollection = new ArrayList<Individual>();
date = obj.getString("date");
TimeInterval interval = getDate(date);
if (interval != null) individualCollection.add(interval);
for (Map.Entry<String, String> entry: entries)
individualCollection.add(Utils.createPersonFromNameEmail(entry.getKey(), entry.getValue(), model));
resultSet.addResult(individualCollection);
c++;
if (c > 100) break;
}
logger.info("Returning " + c + " emails.");
return resultSet;
}
private TimeInterval getDate(String date) {
TimeInterval interval = null;
long ms = 0;
if (date != null) {
try {
ms = (rfc2822DateFormatter.parse(date)).getTime();
interval = TimeInterval.createFromMoment(ms, model);
} catch (ParseException e) {
logger.error("RFC2822 Date Parsing failed: " + date + " " + e.getMessage());
}
} else {
logger.info("Date is null!");
}
return interval;
}
public void execute(String[] emails) {
setFlags[0] = true;
setFlags[1] = true;
setFlags[2] = true;
Collections.addAll(queryEmails, emails);
query();
}
private class ResultSetImpl implements IResultSet {
private String result;
private ResultIterator resultIterator = new ResultIterator(model);
public ResultSetImpl (String result) {this.result = result;}
public void addResult(List<Individual> individuals) {
this.resultIterator.add(individuals);
}
@Override
public String printResults() {
return result;
}
@Override
public IResultIterator iterator() {
return resultIterator;
}
}
}