/**
*
*/
package com.trendrr.oss.executionreport;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.trendrr.oss.StringHelper;
import com.trendrr.oss.TimeAmount;
import com.trendrr.oss.Timeframe;
import com.trendrr.oss.concurrent.PeriodicLock;
/**
*
* An abstract ExecutionReportSerializer useful for implementing on Key Value type storage.
*
*
* @author Dustin Norlander
* @created Sep 20, 2011
*
*/
public abstract class AbstractExecutionReportDBConnector implements
ExecutionReportSerializer {
protected static Log log = LogFactory
.getLog(AbstractExecutionReportDBConnector.class);
public AbstractExecutionReportDBConnector() {
// timeframes.add(Timeframe.MINUTES);
// timeframes.add(Timeframe.HOURS);
// timeframes.add(Timeframe.DAYS);
}
/* (non-Javadoc)
* @see com.trendrr.oss.executionreport.ExecutionReportConnector#save(com.trendrr.oss.executionreport.ExecutionReport, java.util.List)
*/
@Override
public void save(ExecutionReport report, List<ExecutionReportPoint> points) {
if (points == null || points.isEmpty()) {
return;
}
Date ts = new Date();
for (ExecutionReportPoint p : points) {
Date t = p.getTimestamp();
if (t == null) {
t = ts;
}
for (TimeAmount f : report.getConfig().getTimeAmounts()) {
try {
ExecutionReportPointId id = ExecutionReportPointId.instance(
p.getFullname(), p.getTimestamp(), f);
this.inc(id, p.getVal(), p.getMillis());
} catch (Exception x) {
log.error("Caught", x);
}
}
}
}
/**
* saves, database implementations should just override this method and can be satisfied.
* @param id
* @param val
* @param millis
*/
protected abstract void inc(ExecutionReportPointId id, long val, long millis);
/**
* load points based on id. any db implimentation should implement this method.
* @param ids
* @return
*/
protected abstract List<ExecutionReportPoint> load(List<ExecutionReportPointId> ids);
protected int maxItems = 500;
// protected ConcurrentHashMap<String, Collection<String>> childrenCache = new ConcurrentHashMap<String,Collection<String>>();
public abstract void saveChildList(String parentFullname,
Collection<String> childrenFullnames,Date date, TimeAmount timeamount);
/* (non-Javadoc)
* @see com.trendrr.oss.executionreport.ExecutionReportConnector#saveChildren(java.lang.String, java.util.Collection)
*/
@Override
public void saveChildren(String parentFullname,
Collection<String> childrenFullnames, Date date, TimeAmount timeamount) {
// //just to avoid a leak
// if (childrenCache.size() > this.maxItems) {
// childrenCache.clear();
// }
//
// Collection<String> cached = childrenCache.get(parentFullname);
// if (cached != null) {
// if (cached.size() == childrenFullnames.size() && cached.containsAll(childrenFullnames)) {
// //collections are equal, no need to save
// return;
// }
// }
// this.childrenCache.put(parentFullname, childrenFullnames);
this.saveChildList(parentFullname, childrenFullnames, date, timeamount);
}
/* (non-Javadoc)
* @see com.trendrr.oss.executionreport.ExecutionReportConnector#findChildren(java.lang.String)
*/
@Override
public abstract List<String> findChildren(String parentFullname, Date date, TimeAmount timeamount);
/* (non-Javadoc)
* @see com.trendrr.oss.executionreport.ExecutionReportConnector#load(java.lang.String, java.util.Date, java.util.Date, com.trendrr.oss.Timeframe)
*/
@Override
public List<ExecutionReportPoint> load(String fullname, Date start,
Date end, TimeAmount timeamount) {
int startTE = timeamount.toTrendrrEpoch(start).intValue();
int endTE = timeamount.toTrendrrEpoch(end).intValue();
List<ExecutionReportPointId> ids = new ArrayList<ExecutionReportPointId> ();
for (int te = startTE; te <= endTE; te++) {
Date timestamp = timeamount.fromTrendrrEpoch(te);
try {
ExecutionReportPointId id = ExecutionReportPointId.instance(fullname, timestamp, timeamount);
ids.add(id);
} catch (Exception x) {
log.error("Caught", x);
}
}
return this.load(ids);
}
@Override
public List<ExecutionReportChildPoints> loadChildren(String fullname, Date start, Date end, TimeAmount timeframe){
try {
int startTE = timeframe.toTrendrrEpoch(start).intValue();
int endTE = timeframe.toTrendrrEpoch(end).intValue();
//load the parents.
HashMap<String, ExecutionReportChildPoints> pointsByParentId = new HashMap<String, ExecutionReportChildPoints>();
HashMap<String, String> childIdToParentId = new HashMap<String, String>();
TreeSet<String> childrenNames = new TreeSet<String>();
childrenNames.addAll(this.findChildren(fullname, end, timeframe));
childrenNames.addAll(this.findChildren(fullname, start, timeframe));
List<ExecutionReportPointId> ids = new ArrayList<ExecutionReportPointId> ();
for (int te = startTE; te <= endTE; te++) {
Date timestamp = timeframe.fromTrendrrEpoch(te);
try {
ExecutionReportPointId id = ExecutionReportPointId.instance(fullname, timestamp, timeframe);
ids.add(id);
ExecutionReportChildPoints point = new ExecutionReportChildPoints();
point.setId(id);
pointsByParentId.put(id.toString(), point);
for (String n : childrenNames) {
ExecutionReportPointId cId = ExecutionReportPointId.instance(n, timestamp, timeframe);
ids.add(cId);
childIdToParentId.put(cId.toString(), id.toString());
}
} catch (Exception x) {
log.error("Caught", x);
}
}
List<ExecutionReportPoint> points = this.load(ids);
for (ExecutionReportPoint p : points) {
String id = p.getId().toString();
ExecutionReportChildPoints ps = pointsByParentId.get(id);
if (ps != null) {
//this is the parent val!
ps.setFullname(p.getFullname());
ps.setId(p.getId());
ps.setMillis(p.getMillis());
ps.setTimestamp(p.getTimestamp());
ps.setVal(p.getVal());
} else {
//this is the child point.
ExecutionReportChildPoints parent = pointsByParentId.get(childIdToParentId.get(id));
parent.addChildPoint(p);
}
}
List<ExecutionReportChildPoints> pts = new ArrayList<ExecutionReportChildPoints>();
pts.addAll(pointsByParentId.values());
return pts;
} catch (Exception x) {
log.error("Caught", x);
}
return new ArrayList<ExecutionReportChildPoints>();
}
}