/**
*
*/
package com.taobao.top.analysis.node.operation;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.taobao.top.analysis.statistics.data.DistinctCountEntryValue;
import com.taobao.top.analysis.statistics.data.Report;
import com.taobao.top.analysis.statistics.data.ReportEntry;
import com.taobao.top.analysis.statistics.data.impl.SimpleFilter;
import com.taobao.top.analysis.util.AnalysisConstants;
import com.taobao.top.analysis.util.ReportUtil;
/**
* 创建报表的可执行类,用于异步化执行创建报表操作
* @author fangweng
* @Email fangweng@taobao.com
* 2011-11-29
*
*/
public class CreateReportOperation implements Runnable {
private static final Log logger = LogFactory.getLog(CreateReportOperation.class);
String reportFile;
Report report;
Map<String,Map<String, Object>> entryResultPool;
List<String> reports;
CountDownLatch countDownLatch;
String outputEncoding;
public CreateReportOperation(String reportFile,Report report,Map<String,
Map<String, Object>> entryResultPool,List<String> reports,CountDownLatch countDownLatch,String outputEncoding)
{
this.reportFile = reportFile;
this.report = report;
this.entryResultPool = entryResultPool;
this.reports = reports;
this.countDownLatch = countDownLatch;
this.outputEncoding = outputEncoding;
}
@Override
public void run()
{
createReportFile(reportFile,report,entryResultPool,reports,countDownLatch,outputEncoding);
}
//add by fangweng 2011 performance
//通过不排序和增加对map访问来减少对mem的利用,但是在性能上或者速度上也许有影响
private void createReportFile(String reportFile,Report report,Map<String,
Map<String, Object>> entryResultPool,List<String> reports,CountDownLatch countDownLatch,String outputEncoding)
{
BufferedWriter bout = null;
boolean needTitle=false;
try {
File file=new File(reportFile);
if(!file.exists()) {
needTitle=true;
file.createNewFile();
}
if(report.isAppend()){
bout = new BufferedWriter(new java.io.OutputStreamWriter(
new java.io.FileOutputStream(file,true),
outputEncoding));
}else{
bout = new BufferedWriter(new java.io.OutputStreamWriter(
new java.io.FileOutputStream(file),
outputEncoding));
}
if (report.getReportEntrys() != null && report.getReportEntrys().size() > 0)
{
List<ReportEntry> rs = report.getReportEntrys();
//输出title
if(needTitle)
for(int i =0 ; i < rs.size(); i++)
{
ReportEntry entry = report.getReportEntrys().get(i);
bout.write(entry.getName());
if (i == rs.size() -1)
bout.write("\r\n");
else
bout.write(",");
}
//按行开始输出内容
for(int i = 0 ; i < rs.size(); i++)
{
ReportEntry entry = report.getReportEntrys().get(i);
Map<String, Object> m = entryResultPool.get(entry.getId());
if (m == null || (m != null && m.size() == 0))
continue;
Iterator<String> iter = m.keySet().iterator();
while(iter.hasNext())
{
String key = iter.next();
// 作average的中间临时变量不处理
if (key.startsWith(AnalysisConstants.PREF_SUM)
|| key.startsWith(AnalysisConstants.PREF_COUNT)) {
continue;
}
boolean needProcess = true;
//判断是否前面已经有输出
for(int j = 0; j < i; j++)
{
if (entryResultPool.get(report.getReportEntrys().get(j).getId()) != null
&& entryResultPool.get(report.getReportEntrys().get(j).getId()).containsKey(key))
{
needProcess = false;
break;
}
}
if (needProcess)
{
for(int j = 0 ; j < i ; j++)
{
bout.write("0,");
}
for(int j = i ; j < rs.size(); j++)
{
ReportEntry tmpEntry = report.getReportEntrys().get(j);
Object value = null;
if (entryResultPool.get(tmpEntry.getId()) != null)
value = entryResultPool.get(tmpEntry.getId()).get(key);
List<String> formatStack =((SimpleFilter) tmpEntry.getValueFilter()).getFormatStack();
if (value != null && formatStack != null
&& formatStack.size() > 0) {
value = ReportUtil.formatValue(
formatStack, value);
}
if (value != null)
{
//support distinct count
if (value instanceof DistinctCountEntryValue)
{
bout.write(String.valueOf(((DistinctCountEntryValue)value).getCount().get()));
}
else
{
if (value.toString().indexOf(",") != -1)
bout.write("\"" + value.toString() + "\"");
else
bout.write(value.toString());
}
}
else
bout.write("0");
if (j != rs.size() -1)
bout.write(",");
else
bout.write("\r\n");
}
}//end need process one key
}//end loop one map
}//end all entrys
// 周期类报表就输出一次,结果将会被删除
// if (report.isPeriod())
// {
// for(int i = 0 ; i < rs.size(); i++)
// {
//
// Map<String, Object> _deleted = entryResultPool
// .remove(report.getReportEntrys().get(i).getId());
//
// if (_deleted != null)
// _deleted.clear();
//
// }
// }
}
if (!report.isPeriod()) {
reports.add(reportFile);
file.renameTo(new File(reportFile.substring(0, reportFile.indexOf(".temp"))));
}
} catch (Exception ex) {
logger.error(ex, ex);
} finally {
countDownLatch.countDown();
if (bout != null)
try {
bout.close();
} catch (IOException e) {
logger.error(e, e);
}
}
}
}